Table of contents
disclaimer (according to the comments to the previous article)
Domain name
The last time we ended up on that in the docker container launched a web server NGINX, distributing static index.html file. This time we will expand the functionality of the web server by adding data encryption and forced redirects from http to https.
To do this, you need to solve an organizational problem: the fact is that the encryption certificate can be obtained only for a domain name or a group of names. For this reason, we go to any of the domain name registrars and choose a name that matches the brand (purpose, slogan, etc.) without forgetting about the purpose of top-level domain names . In my case, dartservice.ru is perfect . During the registration process, you must fill out the owner information form including name, postal address and email. Then you need to go to the management of DNS records in the registrar's control panel and make three records:
- At least two NS records. These are the names of the domain name servers of the registrar and their name is provided by the registrar when purchasing a domain name.
- A record. It is directly a record of the relationship between the domain name and the server's IP address.
In my case, DNS records look like this:
Having done this, you should not expect an immediate result. Exchange of information between DNS servers usually takes from 1 to 12 hours for the RU zone. Then ... add another test to the project /test/http/client.http
SSL
In general, of course, SSL is an outdated name. The new versions of the protocol are called TLS 1.0 ... 1.3, but the mechanism remains the same - data encryption during the transition between the application layer protocol (in our case HTTP) and the transport layer protocol (TCP / IP). In fact, you need:
- Obtain an encryption certificate from a special certification authority, confirming the ownership of the corresponding domain.
- NGINX.
- .
- , http https.
It is generally accepted at the moment to use free certificates automatically issued by the Let's encrypt service . One of the limitations of such certificates is the validity period. Only 90 days. After that, the certificate must be obtained again. For automatic (without human intervention) obtaining certificates, the ACME protocol and applications were developed that periodically perform actions to confirm domain ownership. Let's encrypt recommends using the certbot app . It is written in python and requires its own repository and python3 to be installed. Therefore, we will use a docker container with certbot installed from the DockerHub registry . Let's select the latest stable version of certbot / certbot: v1.5.0...
Now let's figure out the mechanism for obtaining a certificate using the ACME protocol:
- At the first launch, Certbot generates a private and public key, then creates a domain administrator account in the Let's encrypt service, transferring the public key and domain information.
- After that Let's encrypt sends a message, which certbot must sign with a private key and return it back.
- ertbot must place on the server a special file available for reading at dartservice.ru/.well-known/acme-challenge to confirm ownership of this domain.
- Certbot composes a certificate request , sends it to Let's encrypt and receives a certificate for the domain in return.
Let's add the application container to our script docker-compose.yaml :
New parameter here comand : here is the command that will be executed after the container starts. In this case, certonly (get a certificate). Obtaining a certificate takes place online, that is, it is necessary to consistently answer several questions. Passing flags after the command allows you to do this without human intervention: --webroot (confirmation method) --webroot-path = / usr / share / nginx / html / letsencrypt (path where domain ownership confirmation files will be placed) --email admin @ email.com (domain administrator mail) --agree-tos(we accept the terms of the license agreement) --no-eff-email (do not report email to certbot developers) -d dartservice.ru (list of domains).
Let's configure the NGINX container: The
changes here are to open the https port (443) and mount the folders with the SSL certificate and domain ownership confirmation files.
An important parameter is the Diffie-Hellman key folder. In short: this key is needed in order to securely exchange encryption keys between the server and the client when establishing a connection. More details here .
Let's generate such a key, but we will face the following problem: the key is created by the openssl program, it is a Linux console utility that is unlikely to show up on our Windows machine. The simplest solution is to run our script, go to the web container console and create a key there, passing the host folder mounted to the container in the output path for the file:
Run the script:
docker-compose up -d
We request a list of running containers:
docker-compose ps
Open the container console:
docker exec -it srv_web_1 bash
We start generating the key in the NGINX configuration folder (which, as we remember, is mounted from the host):
openssl dhparam -out /etc/nginx/conf.d/dhparams.pem 2048
Move the key to ./dhparams/dhparam-2048.pem
Exit the container console Ctrl-D , stop the script:
docker-compose down
Now let's change the NGINX configuration ./conf.d/defaulf.conf :
Add a new location ^ ~ /.well-known/acme-challenge to serve static files from the / usr / share / nginx / html / letsencrypt folder . This is where the certbot confirmation files will be placed. Let's set up a redirect for all other requests to https.
Everything is ready for the first SSL certificate.
Let's copy our project to the VPS into a new folder / opt / srv_1 / with the command:
scp -r ./* root@91.230.60.120:/opt/srv_1/
Let's connect from VScode via SSH to VPS.
Let's go to the folder of the running server:
cd /opt/srv_0/
and stop the script:
docker-compose down
Now go to the new server folder cd / opt / srv_1 / and run the script:
docker-compose up
In the console, we see that certbot created a confirmation file zeS4O87S6AfRQ3Kj4MaBlBFZx3AIiWdPn61DwogDMK4 and reported this to the Let's encrypt service, which, in turn, requested this file from four different IP addresses and then issued a certificate. The certificate in the form of a complete chain and a private key were saved in the corresponding folder. The certificate is valid for 90 days (until 05.10.2020).
It's time to create a second location for a secure connection in the NGINX configuration on the server ./conf.d/defaulf.conf :
Restart the script
docker-compose restart
Let's see how the browser reacts to our certificate:
Google Chrome is happy with our certificate. Now the task is more complicated - we will test the security and availability for different browsers of our SSL connection https://www.ssllabs.com/ssltest/ . We enter the address, and we get the result:
Everything is fine with the certificate and key exchange (thanks to Diffie-Hellman), but the test robot has lowered the rating ("B" is "4" in our opinion) for supporting the outdated TLS1.0 and TLS1.1 protocols ... Disabling them in the NGINX configuration is not difficult, however, looking at the test report further, we see that, for example, the browsers of some mobile devices in this case will not be able to connect:
There are still several service tasks left to perform.
The number of attempts to obtain a certificate for a domain must not exceed 5 within 7 days. After that, the Let's encrypt service can block us. However, running the script during development every time certbot will try to do this, so in the docker-compose.dev.yaml script, change the command parameter of the certbot container :
The --dry-run flag is a test run without getting a certificate.
Let's write a test:
Source code github .
Conclusion
So, in this step, we secured communications between the server and client applications and taught browsers to "trust" our domain.
In the next article, we will write a flutter web page with a countdown to the launch of our service, collect it and place it on our server.