Kuinka luoda helppo ja turvallinen käänteinen välityspalvelin Docker, Nginx & Letsencrypt -sovelluksella

Johdanto

Oletko koskaan yrittänyt perustaa jonkinlaista palvelinta kotona? Missä sinun on avattava uusi portti jokaista palvelua varten? Ja on muistettava, mikä portti mihin palveluun menee ja mikä on koti-ip? Tämä on ehdottomasti jotain, joka toimii, ja ihmiset ovat tehneet sitä pisimpään.

Eikö olisikaan mukavaa kirjoittaa plex.example.com ja saada välitön pääsy mediapalvelimellesi? Juuri käänteinen välityspalvelin tekee sinulle, ja yhdistämällä se Dockeriin se on helpompaa kuin koskaan.

Edellytykset

Docker ja Docker-säveltäminen

Sinulla on oltava Docker-versio 17.12.0+ ja Compose-versio 1.21.0+.

Verkkotunnus

Sinulla on oltava määritetty toimialue ja siihen liitettävä SSL-varmenne. Jos sinulla ei ole sellaista, seuraa oppaita täällä, kuinka saada ilmainen LetsEncryptin avulla.

Mitä tämä artikkeli kattaa

Uskon vakaasti ymmärtämään mitä teet. Oli aika, jolloin seurasin oppaita, eikä minulla ole aavistustakaan virheiden vianmäärityksestä. Jos haluat tehdä sen näin, tässä on upea opetusohjelma, joka käsittelee sen määrittämisen. Vaikka artikkelini ovat pitkiä, sinun pitäisi päätyä ymmärtämään, miten kaikki toimii.

Opit täällä, mikä on käänteinen välityspalvelin, miten se asetetaan ja miten voit suojata sen. Teen parhaani jakaa aihe osiin, jotka on jaettu otsikoilla, joten voit hypätä osion yli, jos haluat. Suosittelen lukemaan koko artikkeli ensin kerran, ennen kuin aloitat sen asettamisen.

Mikä on käänteinen välityspalvelin?

Säännöllinen välityspalvelin

Aloitetaan tavallisen välityspalvelimen käsitteestä. Vaikka tämä on termi, joka on hyvin yleinen teknologiayhteisössä, se ei ole ainoa paikka, jota sitä käytetään. Välityspalvelin tarkoittaa, että tiedot käyvät läpi kolmannen osapuolen ennen sijaintiin pääsyä.

Oletetaan, että et halua palvelun tuntevan IP-osoitettasi, voit käyttää välityspalvelinta. Välityspalvelin on palvelin, joka on määritetty nimenomaan tätä tarkoitusta varten. Jos käyttämäsi välityspalvelin sijaitsee esimerkiksi Amsterdamissa, ulkomaille näytettävä IP on Amsterdamin palvelimen IP. Ainoat, jotka tietävät IP-osoitteesi, hallitsevat välityspalvelinta.

Käänteinen välityspalvelin

Jos haluat jakaa sen yksinkertaisiin termeihin, välityspalvelin lisää kerroksen peittämistä. Se on sama käsite käänteisessä välityspalvelimessa, paitsi että lähtevien yhteyksien peittämisen (verkkopalvelimeen pääsyn sijaan) peitettävät saapuvat yhteydet (ihmiset, jotka käyttävät verkkopalvelinta). Annat yksinkertaisesti URL-osoitteen, kuten example.com , ja aina kun ihmiset käyttävät kyseistä URL-osoitetta, käänteinen välityspalvelimesi huolehtii siitä, mihin pyyntö menee.

Oletetaan, että sinulla on kaksi palvelinta määritetty sisäiseen verkkoon. Palvelin1 on 192.168.1.10 ja Server2 on 192.168.1.20. Tällä hetkellä käänteinen välityspalvelimesi lähettää osoitteesta example.com tulevia pyyntöjä Server1: lle. Eräänä päivänä sinulla on joitain päivityksiä verkkosivulle. Sen sijaan, että ottaisit verkkosivuston huollettavaksi, teet vain uuden asennuksen Server2: lla. Kun olet valmis, vaihdat yksinkertaisesti yhden rivin käänteisessä välityspalvelimessa, ja nyt pyynnöt lähetetään Server2: lle. Olettaen, että käänteinen välityspalvelin on määritetty oikein, sinulla ei pitäisi olla mitään seisokkeja.

Mutta ehkä käänteisen välityspalvelimen suurin etu on, että palveluita voi käyttää monilla porteilla, mutta sinun on avattava vain portit 80 ja 443, HTTP ja HTTPS. Kaikki pyynnöt tulevat verkkoosi näissä kahdessa portissa, ja käänteinen välityspalvelin hoitaa loput. Kaikella tällä on järkeä, kun aloitamme välityspalvelimen asettamisen.

Säiliön asentaminen

Mitä tehdä

docker-compose.yaml:

version: '3' services: reverse: container_name: reverse hostname: reverse image: nginx ports: - 80:80 - 443:443 volumes: - :/etc/nginx - :/etc/ssl/private

Ensinnäkin sinun on lisättävä uusi palvelu docker-compose-tiedostoon. Voit kutsua sitä mitä haluat, tässä tapauksessa olen valinnut käänteisen . Täällä olen juuri valinnut kuvaksi nginxin , mutta tuotantoympäristössä on yleensä hyvä määrittää versio siltä varalta, että tulevissa päivityksissä tapahtuu koskaan rikkovia muutoksia.

Sitten sinun pitäisi sitoa kaksi kansiota äänenvoimakkuudella. / etc / nginx on paikka, jossa kaikki määritystiedostosi on tallennettu, ja / etc / ssl / private on paikka, johon SSL-varmentesi tallennetaan. On erittäin tärkeää, että määrityskansiota EI OLE isännässäsi, kun aloitat säilön. Kun käynnistät säilön docker-compose-toiminnolla, se luo kansion automaattisesti ja täyttää sen säilön sisällöllä. Jos olet luonut isännälle tyhjän määrityskansion, se asentaa sen ja säilön sisällä oleva kansio on tyhjä.

Miksi se toimii

Tässä osassa ei ole paljon. Enimmäkseen se on kuin minkä tahansa muun astian aloittaminen telakointikomennolla. Tässä sinun tulisi huomata, että sidot portit 80 ja 443. Täältä kaikki pyynnöt tulevat, ja ne välitetään mihin tahansa määrittelemääsi palveluun.

Nginxin määrittäminen

Mitä tehdä

Nyt sinulla pitäisi olla konfigurointikansio isännässäsi. Siirtyminen kyseiseen hakemistoon, sinun pitäisi nähdä joukko erilaisia ​​tiedostoja ja nimetty kansio conf.d. Sisällä conf.dkaikki asetustiedostosi sijoitetaan. Tällä hetkellä on yksi default.conftiedosto, voit mennä eteenpäin ja poistaa sen.

conf.dLuo vielä sisälläsi kaksi kansiota: sites-availableja sites-enabled. Siirry sites-availableensimmäiseen määritystiedostoon ja luo se. Täällä aiomme määrittää Plex-merkinnän, mutta voit käyttää toista palvelua, jonka olet määrittänyt, jos haluat. Ei ole väliä miten tiedostoa kutsutaan, mutta haluan nimetä sen mieluummin plex.conf.

Avaa nyt tiedosto ja kirjoita seuraava:

upstream plex { server plex:32400; } server { listen 80; server_name plex.example.com; location / { proxy_pass //plex; } }

Mene sites-enabledhakemistoon ja kirjoita seuraava komento:

ln -s ../sites-available/plex.conf .

Tämä luo symbolisen linkin toisessa kansiossa olevaan tiedostoon. Nyt on jäljellä vain yksi asia, se on muuttaa nginx.conftiedostoa määrityskansioon. Jos avaat tiedoston, sinun pitäisi nähdä seuraava viimeisenä rivinä:

include /etc/nginx/conf.d/*.conf;

Vaihda se:

include /etc/nginx/conf.d/sites-enabled/*.conf;

Jotta käänteinen välityspalvelin todella toimisi, meidän on ladattava nginx-palvelu uudelleen säiliön sisälle. Suorita isännältä docker exec nginx -t. Tämä suorittaa syntaksitarkistimen kokoonpanotiedostoihisi nähden. Tämän pitäisi antaa syntaksin olevan ok. Suorita nyt docker exec nginx -s reload. Tämä lähettää signaalin nginx-prosessille, että sen pitäisi ladata uudelleen, ja onnittelut! Sinulla on nyt käynnissä käänteinen välityspalvelin, ja sinun pitäisi pystyä käyttämään palvelinta osoitteessa plex.example.com (olettaen, että olet siirtänyt portin 80 palvelimellesi reitittimessäsi).

Vaikka käänteinen välityspalvelimesi toimii, käytät HTTP: tä, joka ei tarjoa mitään salausta. Seuraava osa on kuinka välityspalvelimesi suojataan ja miten saat täydelliset pisteet SSL Labsista.

Miksi se toimii

Määritystiedosto

Kuten näette, plex.conftiedosto koostuu kahdesta osasta. upstreamOsa ja serverosa. Aloitetaan serverosasta. Tässä määrität portin, joka vastaanottaa saapuvat pyynnöt, minkä toimialueen tämän kokoonpanon tulisi vastata ja mihin se lähetetään.

Tapa, jolla tätä palvelinta asennetaan, on tehtävä tiedosto jokaiselle palvelulle, jolle haluat välityspalvelinpyynnöt, joten tietysti tarvitset jonkin tavan erottaa mikä tiedosto vastaanottaa kukin pyyntö. Näin server-namedirektiivi tekee. Sen alapuolella meillä on locationdirektiivi.

Meidän tapauksessamme tarvitsemme vain yhden location, mutta sinulla voi olla niin monta locationdirektiiviä kuin haluat. Kuvittele, että sinulla on verkkosivusto, jossa on käyttöliittymä ja backend. Käyttämästäsi infrastruktuurista riippuen käyttöliittymä on yksi säilö ja taustajärjestelmä toinen säilö. Sinulla voi olla, location / {}mikä lähettää pyyntöjä käyttöliittymälle ja location /api/ {}mikä lähettää pyyntöjä taustajärjestelmälle. Yhtäkkiä sinulla on useita palveluja käynnissä yhdellä ikimuistoisella verkkotunnuksella.

Mitä tulee upstreamosaan, jota voidaan käyttää kuormituksen tasapainottamiseen. Jos haluat oppia lisää siitä, miten se toimii, voit tutustua virallisiin asiakirjoihin täällä. Yksinkertaisessa tapauksessa määrität vain palvelun isäntänimen tai IP-osoitteen, johon haluat välityspalvelimen, ja mikä portti on välitettävä, ja viittaat sitten alkupään nimiin locationdirektiivissä.

Isäntänimi vs. IP-osoite

Tehdään esimerkki ymmärtääksesi, mikä isäntänimi on. Oletetaan, että olet kotiverkossasi 192.168.1.0. Sitten määrität palvelimen 192.168.1.10: lle ja suoritat Plexin siinä. Voit nyt käyttää Plexiä 192.168.1.10:32400-palvelussa , kunhan olet edelleen samassa verkossa. Toinen mahdollisuus on antaa palvelimelle isäntänimi. Tässä tapauksessa annamme sille isäntänimen plex . Nyt pääset Plexiin kirjoittamalla selaimeesi plex: 32400 !

Tämä sama käsite otettiin käyttöön docker-compose-versiossa 3. Jos tarkastelet docker-compose-tiedostoa aiemmin tässä artikkelissa, huomaat, että annoin sille hostname: reversedirektiivin. Nyt kaikki muut säilöt voivat käyttää käänteistä välityspalvelinta isäntänimellä. Yksi asia, joka on erittäin tärkeä huomata, on se, että palvelun nimen on oltava sama kuin isäntänimi. Tämän telakointikomponentin luojat päättivät asettaa.

Toinen todella tärkeä asia on muistaa, että oletusarvoisesti telakointikontit asetetaan omaan verkkoonsa. Tämä tarkoittaa, että et voi käyttää säilöä sen isäntänimellä, jos istut kannettavalla tietokoneella isäntäverkossasi. Vain säilöt voivat käyttää toisiaan isäntänimellään.

So to sum it up and make it really clear. In your docker-compose file, add the hostname directive to your services. Most of the time your containers will get a new IP every time you restart the container, so referring to it via hostname, means it doesn’t matter what IP your container is getting.

Sites-available & Sites-enabled

Why are we creating the sites-available and sites-enabled directories? This is not something of my creation. If you install Nginx on a server, you will see that it comes with these folders. However because Docker is built with microservices in mind, where one container should only ever do one thing, these folders are omitted in the container. We’re recreating them again, because of how we’re using the container.

And yes, you could definitely just make a sites-enabled folder, or directly host your configuration files in conf.d. Doing it this way, enables you to have passive configuration laying around. Say that you are doing maintenance, and don’t want to have the service active; you simply remove the symbolic link, and put it back when you want the service active again.

Symbolic Links

Symbolic links are a very powerful feature of the operating system. I had personally never used them before setting up an Nginx server, but since then I’ve been using them everywhere I can. Say you are working on 5 different projects, but all these projects use the same file in some way. You can either copy the file into every project, and refer to it directly, or you can place the file in one place, and in those 5 projects make symlinks to that file.

This gives two advantages: you take up 4 times less space than you otherwise would have, and then the most powerful of them all; change the file in one place, and it changes in all 5 projects at once! This was a bit of a sidestep, but I think it’s worth mentioning.

Securing Nginx Proxy

What to Do

Go to your config folder, and create 3 files and fill them with the following input:

common.conf:

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; add_header X-Frame-Options SAMEORIGIN; add_header X-Content-Type-Options nosniff; add_header X-XSS-Protection "1; mode=block";

common_location.conf:

proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Host $host; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Port $server_port;

ssl.conf:

ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ecdh_curve secp384r1; ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384 OLD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 OLD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"; ssl_prefer_server_ciphers on; ssl_dhparam /etc/nginx/dhparams.pem; ssl_certificate /etc/ssl/private/fullchain.pem; ssl_certificate_key /etc/ssl/private/privkey.pem; ssl_session_timeout 10m; ssl_session_cache shared:SSL:10m; ssl_session_tickets off; ssl_stapling on; ssl_stapling_verify on;

Now open the plex.conf file, and change it to the following (notice lines 6, 9, 10 & 14):

upstream plex { server plex:32400; } server { listen 443 ssl; server_name plex.example.com; include common.conf; include /etc/nginx/ssl.conf; location / { proxy_pass //plex; include common_location.conf; } }

Now go back to the root of your config folder, and run the following command:

openssl dhparam -out dhparams.pem 4096

This will take a long time to complete, even up to an hour in some cases.

If you followed my article on getting a LetsEncrypt SSL Certificate, your certificates should be located in /etc/letsencrypt/live// .

When I helped a friend set this up on his system, we ran into some problems where it couldn’t open the files when they were located in that directory. Most likely the cause of some permissions problems. The easy solution to this is to make an SSL directory, like /certs, and then mount that to the Nginx container’s /etc/ssl/private folder. In the newly created folder, you should then make symbolic links, to the certs in your LetsEncrypt’s config folder.

When the openssl command is done running, you should run the docker exec nginx -t to make sure that all the syntax is correct, and then reload it by running docker exec nginx -s reload. At this point everything should be running, and you now have a working and perfectly secure reverse proxy!

Why it Works

Looking in the plex.conf file, there is only one major change, and that is what port the reverse proxy is listening on, and telling it that it’s an ssl connection. Then there are 3 places where we’re including the 3 other files we made. While SSL is kind of secure by itself, these other files make it even more secure. However if for some reason you don’t want to include these files, you need to move the ssl-certificate and ssl-certificate-keyinside the .conf file. These are required to have, in order for an HTTPS connection to work.

Common.conf

Looking in the common.conf file, we add 4 different headers. Headers are something that the server sends to the browser on every response. These headers tell the browser to act a certain way, and it is then up to the browser to enforce these headers.

Strict-Transport-Security (HSTS)

This header tells the browser that connections should be made over HTTPS. When this header has been added, the browser won’t let you make plain HTTP connection to the server, ensuring that all communication is secure.

X-Frame-Options

When specifying this header, you are specifying whether or not other sites can embed your content into their sites. This can help avoid clickjacking attacks.

X-Content-Type-Options

Say you have a site where users can upload files. There’s not enough validation on the files, so a user successfully uploads a php file to the server, where the server is expecting an image to be uploaded. The attacker may then be able to access the uploaded file. Now the server responds with an image, however the file’s MIME-type is text/plain. The browser will ‘sniff’ the file, and then render the php script, allowing the attacker to do RCE (Remote Code Execution).

With this header set to ‘nosniff’, the browser will not look at the file, and simply render it as whatever the server tells the browser that it is.

X-XSS-Protection

While this header was more necessary in older browsers, it’s so easy to add that you might as well. Some XSS (Cross-site Scripting) attacks can be very intelligent, while some are very rudimentary. This header will tell browsers to scan for the simple vulnerabilities and block them.

Common_location.conf

X-Real-IP

Because your servers are behind a reverse proxy, if you try to look at the requesting IP, you will always see the IP of the reverse proxy. This header is added so you can see which IP is actually requesting your service.

X-Forwarded-For

Sometimes a users request will go through multiple clients before it reaches your server. This header includes an array of all those clients.

X-Forwarded-Proto

This header will show what protocol is being used between client and server.

Host

This ensures that it’s possible to do a reverse DNS lookup on the domain name. It’s used when the server_name directive is different than what you are proxying to.

X-Forwarded-Host

Shows what the real host of the request is instead of the reverse proxy.

X-Forwarded-Port

Helps identify what port the client requested the server on.

Ssl.conf

SSL is a huge topic in and of itself, and too big to start explaining in this article. There are many great tutorials out there on how SSL handshakes work, and so on. If you want to look into this specific file, I suggest looking at the protocols and ciphers being used, and what difference they make.

Redirecting HTTP to HTTPS

The observant ones have maybe noticed that we are only ever listening on port 443 in this secure version. This would mean that anyone trying to access the site via //* would get through, but trying to connect through //* would just get an error. Luckily there’s a really easy fix to this. Make a redirect.conf file with the following contents:

server { listen 80; server_name _; return 301 //$host$request_uri; }

Now just make sure that it appears in your sites-enabled folder, and when you’ve reloaded the Nginx process in the container, all requests to port 80 will be redirected to port 443 (HTTPS).

Final Thoughts

Now that your site is up and running, you can head over to SSL Labs and run a test to see how secure your site is. At the time of writing this, you should get a perfect score. However there is a big thing to notice about that.

Turvallisuuden ja mukavuuden välillä on aina tasapaino. Tässä tapauksessa painot ovat voimakkaasti turvallisuuden puolella. Jos suoritat testin SSL Labsissa ja vierität alaspäin, näet useita laitteita, jotka eivät voi muodostaa yhteyttä sivustoosi, koska ne eivät tue uusia standardeja.

Joten pidä tämä mielessä, kun asetat tätä. Juuri tällä hetkellä palvelin vain kotona, missä minun ei tarvitse huolehtia siitä, että monet ihmiset pääsevät siihen. Mutta jos skannaat Facebookissa, huomaat, että heillä ei ole yhtä suuria pisteitä, mutta heidän sivustoonsa pääsee useammalla laitteella.