Forward Proxy
Proprietà di un Forward Proxy
Gestisce le richieste cliente di accedere a risorse in internet. E' posizionato tra i client e l'internet, e inoltra le richieste a server esterni.
Il server di destinazione vede arrivare la richiesta dal forward proxy e non sa del vero client che l'ha originata.
Può includere filtraggio di contenuto, controlli di accesso e anonimizzazione delle richieste, nascondendo l'indirizzo IP del client.
Posizionato al confine della rete intranet del client.
Esercizio con Versione Debian e Ubuntu
Creare la directory di esercizio:
mkdir 01net2-ccli-cproxy-cweb
cd 01net2-ccli-cproxy-cweb
NOTA
L'esercizio è scaricabile come file tar 01net2-ccli-cproxy-cweb.tar
Preparazione dello scaffolding:
mkdir ccli cproxy cweb
touch ccli/Dockerfile cproxy/Dockerfile docker-compose.yml
tree
.
├── ccli
│ └── Dockerfile
├── cproxy
│ └── Dockerfile
├── cweb
└── docker-compose.yml
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"]
L'immagine Ubuntu di base è così scarna che non ha il comando ping
e nemmeno il comando ip
. Così, a scopo di debugging, vengono aggiunti i pacchetti iproute2
, iputils-ping
e tcpdump
.
La configurazione del proxy viene mappata in un volume esterno, per la persistenza dei dati.
E' necessario creare a mano tale volume:
docker volume create conf
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:
- conf:/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
networks:
net2:
ipv4_address: 192.168.102.12
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:
conf:
external: true
Lancio del progetto:
docker compose up -d
Controllo dei contenitori generati:
docker ps
Verifica Iniziale
Vogliamo verificare che il contenitore one (client) non riesce a connettersi col contenitore three (web server). Tra l'altro sono su due reti diverse e non è configurato il routing.
Connettersi a one:
docker exec -ti one sh
Provare la connessione:
curl http://192.168.102.12
Il comando si blocca: non è raggiungibile. Interrompere con Control-C
Uscire:
exit
Configurazione del Proxy
In una finestra di terminale collegarsi al contenitore two:
docker exec -ti two bash
Lanciare Apache:
apache2ctl -k start
Controllare che i processi siano attivi:
ps wax
Abilitare i moduli proxy, proxy_http, e proxy_connect:
a2enmod proxy proxy_http proxy_connect
Editare il file del modulo di proxy abilitato, scommentando le linee del proxy:
vim /etc/apache2/mods-enabled/proxy.conf
.....
ProxyRequests On
<Proxy *>
AddDefaultCharset off
Require all denied
Require local
</Proxy>
.....
Creare un nuovo Virtual Hosts:
vim /etc/apache2/sites-available/forward-proxy.conf
<VirtualHost *:8080>
ProxyRequests On
ProxyVia On
<Proxy "*">
Require ip 192.168
</Proxy>
ErrorLog ${APACHE_LOG_DIR}/error_forward_proxy.log
CustomLog ${APACHE_LOG_DIR}/access_forward_proxy.log combined
</VirtualHost>
Modificare il file di configurazione delle porte, per aggiungere l'ascolto alla porta 8080:
vim /etc/apache2/ports.conf
Listen 80
Listen 8080
<IfModule ssl_module>
Listen 443
</IfModule>
<IfModule mod_gnutls.c>
Listen 443
</IfModule>
Abilitare il sito virtuale:
a2ensite forward-proxy.conf
Restartare il server:
apache2ctl -k restart
Uscire dal container:
exit
Test del Proxy
Connettersi a one:
docker exec -ti one sh
Occorre configurare la variabile d'ambiente che setta il proxy:
export http_proxy=http://192.168.101.10:8080
Provare la connessione:
curl http://192.168.102.12
<html><body><h1>It works!</h1></body></html>
Prova di Persistenza Dati
Fermare e ristartare il progetto:
docker compose down
docker compose up -d
La configurazione precedente è rimasta perchè mantenuta nel volume conf
.
Attivare il server proxy:
docker exec two apache2ctl -k start
Attenzione a non dare l'opzione -ti
. Questa crea un terminale di collegamento, fa partire il server, poi il comando termina, il terminale muore e il processo apache2
rimane senza terminale di controllo e si trasforma in un processo zombie. L'unico modo di uscirne è di ristartare il progetto.
Il client ha lo stesso comportamento di prima.
Connettersi a one:
docker exec -ti one sh
Provare la connessione:
export http_proxy=http://192.168.101.10:8080
curl http://192.168.102.12
Esercizio con Versione Unix su Alpine Docker
Progetto
Nella stessa locazione dell'esercizio precedente, creare una nuova directory:
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
è:
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: 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
networks:
net2:
ipv4_address: 192.168.102.12
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
Partenza del progetto:
docker compose up -d
Configurazione
Connessione al proxy:
docker exec -ti two sh
Configurazione:
cd /etc/apache2
vi conf.d/forward-proxy.conf
<VirtualHost *:8080>
ProxyRequests On
ProxyVia On
<Proxy "*">
Require ip 192.168
</Proxy>
ErrorLog logs/error_forward_proxy.log
CustomLog logs/access_forward_proxy.log combined
</VirtualHost>
Modificare il file di configurazione principale:
vi httpd.conf
Nella sezione Listen
, aggiungere la linea:
Listen 8080
Far partire il server:
httpd -k start
Uscire:
exit
Test
Connettersi a one:
docker exec -ti one sh
Configurare il client proxy:
export http_proxy=http://192.168.101.10:8080
Provare la connessione:
curl http://192.168.102.12
<html><body><h1>It works!</h1></body></html>
Naturalmente questa configurazione non resiste ad un docker compose down
. Se desideriamo la persistenza, allora dobbiamo creare un apposito volume docker e mapparlo alla directory di configurazione.