05. [15p] Filtrare pe bridge

Vrem să facem o legătură simplă directă doar între două containere (red și green) astfel încât să comunice între ele fără ca pachetele să fie prelucrate de sistemul host. Pentru aceasta vom scoate interfețele aferente din bridge-ul br0 și vom crea un nou bridge.

Pentru început scoatem interfețele aferente containerelor red (veth-red) și green (veth-green) din bridge-ul br0:

root@host:~# brctl delif br0 veth-red
root@host:~# brctl delif br0 veth-green
root@host:~# brctl show br0
bridge name	bridge id		STP enabled	interfaces
br0		8000.000c2919b1b2	no		eth0
                                                        veth-blue

Creăm un nou bridge (br1) și adăugăm interfețele veth-red și veth-green în acesta:

root@host:~# brctl addbr br1
root@host:~# brctl addif br1 veth-red
root@host:~# brctl addif br1 veth-green
root@host:~# brctl show br1
bridge name	bridge id		STP enabled	interfaces
br1		8000.f67659f52916	no		veth-green
							veth-red
root@host:~# ip l s dev br1 up
root@host:~# ip a s dev br1
13: br1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
[...]

Configurăm adrese pe stațiile red și green și verificăm apoi conectiviatea între acestea. Configurăm adresele 172.16.12.1/24, respectiv 172.16.12.2/24 și verificăm conectivitatea între acestea:

root@red:~# ip a f dev eth0
root@red:~# ip a a 172.16.12.1/24 dev eth0
root@red:~# ip a s dev eth0
9: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:16:3e:8e:84:21 brd ff:ff:ff:ff:ff:ff
    inet 172.16.12.1/24 scope global eth0
 
root@green:~# ip a f dev eth0
root@green:~# ip a a 172.16.12.2/24 dev eth0
root@green:~# ip a s dev eth0
6: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:16:3e:d1:b2:95 brd ff:ff:ff:ff:ff:ff
    inet 172.16.12.2/24 scope global eth0
 
root@red:~# ping 172.16.12.2
PING 172.16.12.2 (172.16.12.2) 56(84) bytes of data.
64 bytes from 172.16.12.2: icmp_req=1 ttl=64 time=0.319 ms
^C
--- 172.16.12.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.319/0.319/0.319/0.000 ms
 
root@green:~# ping 172.16.12.1
PING 172.16.12.1 (172.16.12.1) 56(84) bytes of data.
64 bytes from 172.16.12.1: icmp_req=1 ttl=64 time=0.191 ms
^C
--- 172.16.12.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.191/0.191/0.191/0.000 ms

Avem conectivitate completă între cele două stații (red și green) inclusiv la nivel de serviciu. Stația green poate accesa serviciile SSH, FTP, telnet de pe stația red:

root@green:~# ssh root@172.16.12.1
[...]
root@red:~#

root@green:~# ftp 172.16.12.1
Connected to 172.16.12.1.
220 (vsFTPd 2.3.5)
Name (172.16.12.1:root): [...]
 
root@green:~# telnet 172.16.12.1
Trying 172.16.12.1...
Connected to 172.16.12.1.
Escape character is '^]'.
Ubuntu 12.04.3 LTS
red login: [...]

Ne propunem să blocăm traficul nesigur (adică FTP și telnet) de la stația green la stația red. Avem soluția configurării unui firewall pe stația red folosind utilitarul iptables. Această soluție are două neajunsuri:

De aceea dorim să filtrăm acele pachete direct de pe stația host. Stația host nu face însă prelucrarea pachetelor, acestea trec prin bridge-ul br1 deci nu putem folosi iptables sau alt utilitar de prelucrare a traficului. Soluția o reprezintă însă utilitarul ebtables care permite configurarea de firewall la nivelul bridge-ului.

Pentru început vom instala ebtables pe stația host:

root@host:~# apt-get install ebtables

Apoi configurăm ebtables pentru a împiedica traficul telnet și FTP care vine de la stația green către stația red. Sintaxa este similară iptables:

root@host:~# ebtables -A FORWARD -p IPv4 --ip-src 172.16.12.2 --ip-dst 172.16.12.1 --ip-proto tcp --ip-destination-port 21 -j DROP
root@host:~# ebtables -A FORWARD -p IPv4 --ip-src 172.16.12.2 --ip-dst 172.16.12.1 --ip-proto tcp --ip-destination-port 23 -j DROP
root@host:~# ebtables -L FORWARD 
Bridge table: filter
 
Bridge chain: FORWARD, entries: 2, policy: ACCEPT
-p IPv4 --ip-src 172.16.12.2 --ip-dst 172.16.12.1 --ip-proto tcp --ip-dport 21 -j DROP 
-p IPv4 --ip-src 172.16.12.2 --ip-dst 172.16.12.1 --ip-proto tcp --ip-dport 23 -j DROP

Verificăm din nou, conectivitatea SSH, FTP și telnet de la stația green la stația red:

root@green:~# ssh root@172.16.12.1
[...]
root@red:~# 
 
root@green:~# telnet 172.16.12.1
Trying 172.16.12.1...
^C
root@green:~# ftp 172.16.12.1
^C

Observăm că este în continuare funcțională doar conexiunea SSH, nu și FTP și telnet (blocate folosind ebtables). Avem obiectivul îndeplinit: doar conexiunile sigure (pe porturile implicite) sunt permise între green și red.

ebtables nu are acțiune de tip REJECT ci doar DROP. Astfel, inițiatorul unei conexiuni filtrate nu va fi înștiințat de filtrarea pachetelor. Acestea vor fi filtrate iar inițiatorul va trebui să deducă faptul că există o formă de blocare a pachetelor pe drum.