Reverse Proxy
Proprietà di un Reverse Proxy
Gestisce le richieste di un cliente esterno che accede a risorse nella intranet di un'organizzazione. Compie il forward delle richieste del client all'appropriato backend server.
Usato per load balancing, terminazione di SSL, cache e controlli di sicurezza.
I backend servers vedono la richiesta provenire dal reverse proxy come se questo fosse il client.
Posizionato al confine di ingresso dell'intranet di un'organizzazione, gestisce e controlla le richieste in ingresso.
Casi d'Uso di un Reverse Proxy
Con moduli del proxy server stesso:
- Load Balancing: bilanciamento del carico dei backend server.
- SSL Termination: possono gestire la crittografazione e decrittografazione con SSL/TLS per conto dei backend server.
- Caching: accelerazione dei tempi di responso al client e diminuzione del carico dei backend server.
Con software aggiuntivo installato a bordo del proxy:
- Sicurezza: possono filtrare il contenuto in provenienza dall'internet, e bloccare attacchi DDoS.
- Web Application Firewall (WAF): possono proteggere la sicurezza dell'applicativo dei backend server, impedendo p.es. SQL Injection e Cross Site Scripting (XSS).
- Conversione di Protocollo: possono tradurre richieste da un protocollo ad un altro.
- Compressione ed Ottimizzazione: possono effettuare compressione ed ottimizzazionne dei responsi verso il client, riducendo i tempi di trasferimento.
Moduli Requisiti
mod_proxy
: modulo primario, requisitomod_proxy_http
: gestisce i protocolli HTTP&HTTPSmod_ssl
: supporta i protocolli SSL v3 e TLS v1.x
Esercizio su Debian e Ubuntu
Preparazione
Creare la directory di esercizio:
mkdir -p 02net1-ccli-net2-cproxy-2cweb
cd 02net1-ccli-net2-cproxy-2cweb
Preparare lo scaffolding:
mkdir ccli cproxy cweb
touch ccli/Dockerfile cproxy/Dockerfile docker-compose.yml
Verificare l'albero:
tree
.
├── ccli
│ └── Dockerfile
├── cproxy
│ └── Dockerfile
├── cweb
└── docker-compose.yml
Preparare volumi per la persistenza dati:
docker volume create confrev
docker volume create three-html
docker volume create four-html
docker volume ls
Client
Il client ccli
è un'immagine Alpine abbastanza semplice.
vim ccli/Dockerfile
FROM alpine:3.7
MAINTAINER John Smith <john@stormforce.ac>
RUN apk --update add --no-cache openssh tcpdump curl
CMD ["/bin/sleep","1000000"]
Proxy
Il proxy cproxy
è un'immagine Ubuntu con la versione Debian/Ubuntu di Apache installata, più qualche altra utility.
vim cproxy/Dockerfile
FROM ubuntu
RUN apt update
RUN apt install -y apache2
RUN apt install -y vim curl wget iproute2 iputils-ping tcpdump
EXPOSE 80 443
CMD ["/bin/sleep","1000000"]
Web Server
Il web server cweb
è un'immagine Alpine con la versione Unix di Apache, disponibile su Docker Hub.
docker-compose.yml
Il docker-compose.yml
è:
vim docker-compose.yml
version: '3.6'
services:
one:
build: ccli
image: ccli
container_name: one
hostname: one
cap_add:
- ALL
networks:
net1:
ipv4_address: 192.168.101.11
two:
build: cproxy
image: cproxy
container_name: two
hostname: two
cap_add:
- ALL
volumes:
- confrev:/etc/apache2
networks:
net1:
ipv4_address: 192.168.101.10
net2:
ipv4_address: 192.168.102.10
three:
image: httpd:2.4-alpine
container_name: three
hostname: three
cap_add:
- ALL
volumes:
- three-html:/usr/local/apache2/htdocs/
networks:
net2:
ipv4_address: 192.168.102.12
four:
image: httpd:2.4-alpine
container_name: four
hostname: four
cap_add:
- ALL
volumes:
- four-html:/usr/local/apache2/htdocs/
networks:
net2:
ipv4_address: 192.168.102.13
networks:
net1:
name: net1
ipam:
driver: default
config:
- subnet: 192.168.101.0/24
net2:
name: net2
ipam:
driver: default
config:
- subnet: 192.168.102.0/24
volumes:
confrev:
external: true
three-html:
external: true
four-html:
external: true
Lancio del progetto:
docker compose up -d
Controllo dei contenitori generati:
docker ps
Configurazione
Collegarsi a two ed abilitare il servizio web se non lo è già:
docker exec -ti two bash
apache2ctl -k start
ps wax
Moduli
Abilitare i moduli requisiti:
a2enmod proxy
a2enmod proxy_http
a2enmod ssl
Verificare:
apache2ctl -M
Disabilitare il sito di default
a2dissite 000-default.conf
Creare un nuovo sito virtuale
cd /etc/apache2/sites-available
vim example.com.conf
<VirtualHost *:80>
ServerName site1.com
ServerAlias www.site1.com
ServerAdmin postmaster@site1.com
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
ProxyPass / http://192.168.102.12:80/
ProxyPassReverse / http://192.168.102.12:80/
ProxyRequests Off
</VirtualHost>
ServerName
: nome ufficiale del serverServerAlias
: nomi aggiuntivi accettati dal serverServerAdmin
: posta elettronica dell'amministratoreErrorLog
: file degli erroriCustomLog
: log delle richieste dei client al serverProxyPass
: mappa i server remoti nello spazio locale e definisce gli indirizzi target per la redirezione del traffico. E' il parametro che definisce il server corrente come reverse proxy.ProxyPassReverse
: gestisce i responsi dei backend servers, compiendo una riscrittura dei campi e headers del responso con le proprie informazioni. Questo impedisce che i backend server vengano esposti all'internet.ProxyRequests
: impedisce cge il server venga usato come forward proxy. Dovrebbe tipicamente essere settato adoff
quando si usa ProxyPass.
Abilitare il Virtual Host
a2ensite example.com.conf
Restart
Restartare il server.
apachectl -k restart
ps wax
Uscire:
exit
Verifica
Vogliamo creare pagine web distintive per i downstream servers.
Collegarsi a three:
docker exec -ti three sh
Modificare il file principale di DocumentRoot:
vi /usr/local/apache2/htdocs/index.html
<html><body><h1>It works! I am three</h1></body></html>
exit
Simili cambiamenti su four:
docker exec -ti four sh
Modificare il file principale di DocumentRoot:
vi /usr/local/apache2/htdocs/index.html
<html><body><h1>It works! I am four</h1></body></html>
exit
Collegarsi a one:
docker exec -ti one sh
Collegamento a two:
curl 192.168.101.10
<html><body><h1>It works! I am three</h1></body></html>
Configurazione su Docker Alpine
Progetto 2
Aggiungere al progetto la directory cproxyalp
:
mkdir cproxyalp
Il Dockerfile è:
vim cproxyalp/Dockerfile
FROM alpine
RUN apk add apache2 apache2-proxy apache2-proxy-html curl
EXPOSE 80 443
CMD ["/bin/sleep","1000000"]
Il docker-compose.yml
è:
version: '3.6'
services:
one:
build: ccli
image: ccli
container_name: one
hostname: one
cap_add:
- ALL
networks:
net1:
ipv4_address: 192.168.101.11
two:
build: cproxyalp
image: cproxyalp
container_name: two
hostname: two
cap_add:
- ALL
networks:
net1:
ipv4_address: 192.168.101.10
net2:
ipv4_address: 192.168.102.10
three:
image: httpd:2.4-alpine
container_name: three
hostname: three
cap_add:
- ALL
volumes:
- three-html:/usr/local/apache2/htdocs/
networks:
net2:
ipv4_address: 192.168.102.12
four:
image: httpd:2.4-alpine
container_name: four
hostname: four
cap_add:
- ALL
volumes:
- four-html:/usr/local/apache2/htdocs/
networks:
net2:
ipv4_address: 192.168.102.13
networks:
net1:
name: net1
ipam:
driver: default
config:
- subnet: 192.168.101.0/24
net2:
name: net2
ipam:
driver: default
config:
- subnet: 192.168.102.0/24
volumes:
three-html:
external: true
four-html:
external: true
Partenza del progetto:
docker compose up -d
Configurazione 2
Connessione al proxy:
docker exec -ti two sh
Configurazione:
cd /etc/apache2
vi conf.d/reverse-proxy.conf
<VirtualHost *:80>
ServerName site1.com
ServerAlias www.site1.com
ServerAdmin postmaster@site1.com
ErrorLog logs/error.log
CustomLog logs/access.log combined
ProxyPass / http://192.168.102.12:80/
ProxyPassReverse / http://192.168.102.12:80/
ProxyRequests Off
</VirtualHost>
Disabilitare il forward proxy se esiste:
cd /etc/apache2/conf.d
mv forward-proxy.conf forward-proxy.conf.old 2> /dev/null
Verificare la configurazione:
httpd -t
Startare il server:
httpd -k start