HAProxy - 2 methods for https routing
Recently, there was a project to connect an https web server existing in a private network through the Internet. It is possible to use a VPN, but I decided to study how to use HAProxy.
Please refer to the previous blog for HAProxy installation and basic usage.
<Configuration I want to implement>
Prerequisite
A web server, a certificate, etc. are required to test the content of this article.
The following 3 articles show how to easily build an https web server using Python Prask. Please refer to the building a https web server for testing.
- Python Flask - Running a simple web server
- Python Flask - Give domain name to Flask WebServer
- Python Flask - Give https to Flask WebServer
Be Careful : If you test homepages such as https://www.google.com and https://www.facebook.com, redirects occur frequently. So it is difficult to test accurately. If possible, I recommend creating a simple https web service to test it yourself.
<My test configuration>
Simplest configuration
The https works based on the certificate installed in the web server and validates the server certificate in the client web browser.
SSL encrypted packets are transmitted and received between the browser and the web server. However, on a larger scale, these packets are only part of the TCP/IP packets. If HAProxy does not perform encryption and decryption, but only forwards packets, the encryption algorithm has no effect on operation.
In our previous blog, we've seen how to route a normal tcp packet using HAProxy.
You can think of how to use tcp mode in haproxy.cfg configuration first.
global log /dev/log local0 log /dev/log local1 notice chroot /var/lib/haproxy #stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners stats socket /run/haproxy/admin.sock mode 660 level user expose-fd listeners stats timeout 30s user haproxy group haproxy daemon # Default SSL material locations ca-base /etc/ssl/certs crt-base /etc/ssl/private # Default ciphers to use on SSL-enabled listening sockets. # For more information, see ciphers(1SSL). This list is from: # https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/ # An alternative list with additional directives can be obtained from # https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=haproxy ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS ssl-default-bind-options no-sslv3 defaults log global mode tcp timeout client 50000 timeout server 50000 frontend cti_1_front bind *:8080 mode tcp default_backend cti_1_back backend cti_1_back balance roundrobin server server_1 www.spypiggy2.ga:8080 check
</etc/haproxy/haproxy.cfg at www.spypiggy.ga>
As you can see in the cfg file, packets coming through port 8080 of haproxy are treated as normal TCP packets and are configured to be routed to port 8080 of www.spypiggy2.ga.
The spypiggy2.ga runs the https web server in advance using Flask.
from flask import Flask import ssl app = Flask(__name__) @app.route('/') def index(): return 'Hello Flask' @app.route('/info') def info(): return 'Info' if __name__ == "__main__": ssl_ctx = ssl.SSLContext(ssl.PROTOCOL_TLS) ssl_ctx.load_cert_chain(certfile='/etc/letsencrypt/live/spypiggy2.ga/fullchain.pem', keyfile='/etc/letsencrypt/live/spypiggy2.ga/privkey.pem') app.run(host="221.139.49.53", port="8080", ssl_context=ssl_ctx)
<myhttps.py at www.spypiggy2.ga>
Tips: For more information on creating and using ssl certificate used in the above source code, refer to the previous blogs introduced by Prerequisite.
[root@spypiggy2.ga pyflask]# python3 myhttps.py * Serving Flask app "myhttps" (lazy loading) * Environment: production WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. * Debug mode: off * Running on https://221.139.49.53:8080/ (Press CTRL+C to quit)
You can see that it is waiting for https connection through port 8080 of 221.139.49.53 IP address.
Now let's test it in the browser of the PC. Enter https://117.52.89.240:8080/ in your PC browser. Perhaps the following warning appears.
Press Advanced at the bottom to proceed.
Press Proceed to 117.52.89.240 (unsafe) at the bottom to proceed. Finally you can see the successful result.
<PC Browser www.spypiggy2.ga>
The causes of the above browser warning are as follows.
- The web browser connected to spypiggy.ga using https, but spypiggy.ga sends all packets to spypiggy2.ga.
- All authentication related work takes place in spypiggy2.ga.
- The web browser was authenticated, but the security warning was triggered because the 3rd party certificate was used, not the web server (spypiggy.ga) to which it was accessed.
In the above warning, you can see that it corresponds to "attacker intercepting your connection". However, because this is our intended behavior, we have ignored security warnings. The above warning is inevitable when haproxy, which operates as a reverse proxy, processes packets using tcp.
More accurate configuration
To resolve the above warning, when the client tries to connect to
haproxy which has its own certificate, the authentication process
through certificate exchange must be performed directly.
This time, let's install a certificate in haproxy and set it to go through the https authentication process by directly exchanging the certificate with the client.
Certificate Installation
Please refer to the link of Prerequisite for information on certificate creation. We will start by copying the generated certificate. We created a certificate on the letsencrypt site, and the certificate is stored in the /etc/letsencrypt/live/spypiggy.ga/ directory.
mkdir -p /etc/haproxy/ssl cp /etc/letsencrypt/live/spypiggy.ga/*.pem /etc/haproxy/ssl/
We have to make the certificate and key into a single pem file for use in haproxy.
cat /etc/haproxy/ssl/privkey.pem > /etc/haproxy/ssl/unified.pem cat /etc/haproxy/ssl/fullchain.pem >> /etc/haproxy/ssl/unified.pem
Then, modify haproxy.cfg file as follows.
global log /dev/log local0 log /dev/log local1 notice chroot /var/lib/haproxy #stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners stats socket /run/haproxy/admin.sock mode 660 level user expose-fd listeners stats timeout 30s user haproxy group haproxy daemon # Default SSL material locations ca-base /etc/ssl/certs crt-base /etc/ssl/private # Default ciphers to use on SSL-enabled listening sockets. # For more information, see ciphers(1SSL). This list is from: # https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/ # An alternative list with additional directives can be obtained from # https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=haproxy ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS ssl-default-bind-options no-sslv3 defaults log global mode tcp timeout client 50000 timeout server 50000 frontend cti_1_front #bind *:8080 #mode tcp bind *:8080 ssl crt /etc/haproxy/ssl/unified.pem default_backend cti_1_back backend cti_1_back balance roundrobin server server_1 www.spypiggy2.ga:8080 check maxconn 500 ssl verify none
There are two important parts.
The first is the bind line at the frontend. The ssl parameter enables SSL termination for this listener. The
crt
parameter identifies the location of the
PEM-formatted SSL certificate. This certificate should contain both the
public certificate and private key. And we did this a while ago. The result file is unified.pem.The second important part is using the ssl parameter and verify none when routing at the backend.
As with the frontend, you need to add the ssl parameter to enable ssl and make a request to https. Also, ignore verification of the spypiggy2.ga server, and trust and connect unconditionally, so add verify none.
Now restart haproxy and test again. Only work with haproxy, no need to touch the rest of the system.
systemctl restart haproxy
This time, you can see that the https connection is established without any error.
<PC Browser with no warning!>
If you don't trust spypiggy2.ga, you should change your settings to get the correct authentication credentials between haproxy and spypiggy2.ga.
In this case, because the haproxy is a client, you must use the ca certificate like a web browser on a PC.
In this case, because the haproxy is a client, you must use the ca certificate like a web browser on a PC.
If you remove verify none from the backend part of the haproxy.cfg file and add ca-file, the authentication process of the server connecting through the backend is performed.
If you are a CentOS user, you can use the ca certificate in the following directory.
backend cti_1_back balance roundrobin server server_1 www.spypiggy2.ga:8080 ssl check ca-file /etc/ssl/certs/ca-bundle.crt
If you are an Ubuntu user, you can use the ca certificate in the following directory.
backend cti_1_back balance roundrobin server server_1 www.spypiggy2.ga:8080 ssl check ca-file /etc/ssl/certs/ca-certificates.crt
Wrapping up
We have seen how to handle https in haproxy in 2 ways.
The first tcp mode has the advantage of being very simple to set up, but has the disadvantage of generating a security warning in the browser.
The mode using the second ssl parameter makes https connection with the client browser using haproxy's own certificate, so it is connected without a security warning. However, it is difficult to install and there is a burden to install a certificate. In the test, a free certificate was used, but the free certificate has a short usage period. Paid certificates with a long period of use have the disadvantage of monetary burden.
Make a good comparison of the pros and cons and choose the appropriate method for your environment.
The first tcp mode has the advantage of being very simple to set up, but has the disadvantage of generating a security warning in the browser.
The mode using the second ssl parameter makes https connection with the client browser using haproxy's own certificate, so it is connected without a security warning. However, it is difficult to install and there is a burden to install a certificate. In the test, a free certificate was used, but the free certificate has a short usage period. Paid certificates with a long period of use have the disadvantage of monetary burden.
Make a good comparison of the pros and cons and choose the appropriate method for your environment.
댓글
댓글 쓰기