V rámci virtuálního serveru vytvořte vždy 2 kontejnery propojené vlastní vnitřní síti. Jeden (první) kontejner bude nabízet služby do "veřejné sítě". Konfigurace přes Docker compose.
Kontejner 1 - Firewall a monitorování a logování provozu. Kontejner 2 OpenVPN server
Vytvoříme si Docker compose s 2 sítěma, jedna pro vnitřní komunikaci mezi kontejnery, bez přístupu k "internetu". Druhá pro přístup FW kontejneru do "internetu".
name: virt_project_1
services:
firewall:
build: ./firewall
container_name: firewall
cap_add:
- NET_ADMIN
- NET_RAW
ports:
- "1194:1194/udp" # veřejný port pro VPN
networks:
external-net:
internal-net:
ipv4_address: 10.0.0.3
sysctls:
- net.ipv4.ip_forward=1
volumes:
- ./logs:/var/log/firewall
restart: unless-stopped
openvpn:
image: kylemanna/openvpn
container_name: openvpn
cap_add:
- NET_ADMIN
networks:
internal-net:
ipv4_address: 10.0.0.2
depends_on:
- firewall
volumes:
- ./openvpn-data/conf:/etc/openvpn
expose:
- "1194/udp"
command: >
sh -c "ip route del default || true && ip route add default via 10.0.0.3 && ovpn_run"
networks:
internal-net:
driver: bridge
internal: true
ipam:
config:
- subnet: 10.0.0.0/24
external-net:
driver: bridge
Pro Firewall kontejner si vytvoříme Dockerfile společně s entrypoint.sh skriptem. Tento skript nám nastaví pravidla firewallu pomocí IPtables a zapne monitoring sítě společně s logováním.
FROM debian:bullseye
RUN apt-get update && apt-get install -y \
iptables \
tcpdump \
iputils-ping \
net-tools \
curl \
iproute2 \
ulogd2 \
&& rm -rf /var/lib/apt/lists/*
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
#!/bin/bash
set -e
# Najít správná rozhraní
INTERNAL_IF=$(ip -o -4 addr show | grep "10.0.0" | awk '{print $2}')
EXTERNAL_IF=$(ip -o -4 addr show | grep -v "10.0.0" | grep -v "127.0.0" | awk '{print $2}' | head -n1)
echo "Internal: $INTERNAL_IF, External: $EXTERNAL_IF"
if [ -z "$INTERNAL_IF" ] || [ -z "$EXTERNAL_IF" ]; then
echo "CHYBA: Nelze detekovat rozhraní!"
exit 1
fi
# Vyčistit pravidla
iptables -F
iptables -t nat -F
iptables -X
# Výchozí politiky
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
# Povolit loopback a navázaná spojení
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
# === PING na firewall z internal sítě ===
iptables -A INPUT -i $INTERNAL_IF -p icmp --icmp-type echo-request -j ACCEPT
# === VPN PROVOZ (příchozí z venku) ===
# Logovat příchozí VPN provoz
iptables -A INPUT -i $EXTERNAL_IF -p udp --dport 1194 -j LOG --log-prefix "VPN-IN: "
iptables -A INPUT -i $EXTERNAL_IF -p udp --dport 1194 -j ACCEPT
# DNAT s logováním
iptables -t nat -A PREROUTING -i $EXTERNAL_IF -p udp --dport 1194 -j LOG --log-prefix "DNAT: "
iptables -t nat -A PREROUTING -i $EXTERNAL_IF -p udp --dport 1194 -j DNAT --to-destination 10.0.0.2:1194
# MASQUERADE pro příchozí VPN (KLÍČOVÉ!)
iptables -t nat -A POSTROUTING -o $INTERNAL_IF -d 10.0.0.2 -p udp --dport 1194 -j MASQUERADE
# Forward VPN provozu
iptables -A FORWARD -i $EXTERNAL_IF -o $INTERNAL_IF -d 10.0.0.2 -p udp --dport 1194 -j LOG --log-prefix "FWD-TO-VPN: "
iptables -A FORWARD -i $EXTERNAL_IF -o $INTERNAL_IF -d 10.0.0.2 -p udp --dport 1194 -j ACCEPT
# === ODCHOZÍ PROVOZ z internal sítě (OpenVPN kontejner) ===
# Povolit VEŠKERÝ odchozí provoz z OpenVPN kontejneru
iptables -A FORWARD -i $INTERNAL_IF -o $EXTERNAL_IF -s 10.0.0.0/24 -j LOG --log-prefix "FWD-OUT: "
iptables -A FORWARD -i $INTERNAL_IF -o $EXTERNAL_IF -s 10.0.0.0/24 -j ACCEPT
# MASQUERADE pro VEŠKERÝ odchozí provoz z internal net
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o $EXTERNAL_IF -j MASQUERADE
# Logovat zamítnuté pakety
iptables -A INPUT -j LOG --log-prefix "DROP-IN: " --log-level 4
iptables -A INPUT -j DROP
iptables -A FORWARD -j LOG --log-prefix "DROP-FWD: " --log-level 4
iptables -A FORWARD -j DROP
echo "Firewall pravidla nastavena s monitoringem"
iptables -L -n -v
iptables -t nat -L -n -v
echo "Přesměrovávám kernel logy..."
dmesg -w | tee -a /var/log/firewall/kernel.log &
# === MONITORING ===
mkdir -p /var/log/firewall
# Zachytávání VPN provozu do pcap souboru
echo "Spouštím tcpdump pro monitoring VPN provozu..."
tcpdump -i any -n udp port 1194 -w /var/log/firewall/vpn_traffic.pcap &
# Jednoduchý monitoring loop
echo "Spouštím monitoring loop..."
while true; do
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
echo "[$TIMESTAMP] === Firewall Statistics ===" >> /var/log/firewall/stats.log
iptables -L -n -v -x >> /var/log/firewall/stats.log
echo "" >> /var/log/firewall/stats.log
iptables -t nat -L -n -v -x >> /var/log/firewall/stats.log
echo "======================================" >> /var/log/firewall/stats.log
sleep 60
done
Před prvním spuštěním aplikace je potřeba provést pár kroků spojených s inicializací OpenVPN serveru a jeho konfigurace.
docker compose run --rm openvpn ovpn_genconfig -u udp://IP_ADRESA_VIRTUALU:1194
docker compose run --rm openvpn ovpn_initpki
export CLIENTNAME="pks_virtual"
# with a passphrase (recommended)
docker compose run --rm openvpn easyrsa build-client-full $CLIENTNAME
# without a passphrase (not recommended)
docker compose run --rm openvpn easyrsa build-client-full $CLIENTNAME nopass
docker compose run --rm openvpn ovpn_getclient $CLIENTNAME > $CLIENTNAME.ovpn
docker compose up -d --build
Změna rozsahu odkud jsou přiřazovány adresy aby se nepřekrývaly s docker sítěma, nebo sítí v učebně. float aby prijimal klienty z jakehokoliv portu.
server 172.30.0.0 255.255.255.0 #změna
float #přidat
Vytvořený konfigurační soubor klienta zkopírujeme a přeneseme na vybrané zařízení. Pro testování jsem jako klienta zvolil PKS virtuál, kde jsem konfiguraci přenesl přes SCP.
openvpn --config pks_virtual.ovpn &
tshark -r vpn_traffic.pcap
1 0.000000 192.168.0.29 → 172.18.0.2 OpenVPN 90 MessageType: P_CONTROL_HARD_RESET_CLIENT_V2
2 0.000068 10.0.0.3 → 10.0.0.2 OpenVPN 90 MessageType: P_CONTROL_HARD_RESET_CLIENT_V2
3 0.000518 10.0.0.2 → 10.0.0.3 OpenVPN 102 MessageType: P_CONTROL_HARD_RESET_SERVER_V2
4 0.000531 172.18.0.2 → 192.168.0.29 OpenVPN 102 MessageType: P_CONTROL_HARD_RESET_SERVER_V2
5 0.000827 192.168.0.29 → 172.18.0.2 TLSv1 379 Client Hello
6 0.000835 10.0.0.3 → 10.0.0.2 TLSv1 379 Client Hello
7 0.003523 10.0.0.2 → 10.0.0.3 OpenVPN 98 MessageType: P_ACK_V1
8 0.003533 172.18.0.2 → 192.168.0.29 OpenVPN 98 MessageType: P_ACK_V1
9 0.003614 10.0.0.2 → 10.0.0.3 TLSv1.3 1208 Server Hello, Change Cipher Spec, Application Data, Application Data
10 0.003620 172.18.0.2 → 192.168.0.29 TLSv1.3 1208 Server Hello, Change Cipher Spec, Application Data, Application Data
11 0.003663 10.0.0.2 → 10.0.0.3 TLSv1.3 1208 Continuation Data
12 0.003683 172.18.0.2 → 192.168.0.29 TLSv1.3 1208 Continuation Data
13 0.003739 10.0.0.2 → 10.0.0.3 TLSv1.3 221 Continuation Data
14 0.003743 172.18.0.2 → 192.168.0.29 TLSv1.3 221 Continuation Data
15 0.004219 192.168.0.29 → 172.18.0.2 OpenVPN 102 MessageType: P_ACK_V1
16 0.004227 10.0.0.3 → 10.0.0.2 OpenVPN 102 MessageType: P_ACK_V1
17 0.005135 192.168.0.29 → 172.18.0.2 OpenVPN 106 MessageType: P_ACK_V1
18 0.005139 10.0.0.3 → 10.0.0.2 OpenVPN 106 MessageType: P_ACK_V1
19 0.007547 192.168.0.29 → 172.18.0.2 TLSv1.3 1270 Change Cipher Spec
20 0.007552 10.0.0.3 → 10.0.0.2 TLSv1.3 1270 Change Cipher Spec
21 0.007568 192.168.0.29 → 172.18.0.2 TLSv1.3 1270 Continuation Data
22 0.007572 10.0.0.3 → 10.0.0.2 TLSv1.3 1270 Continuation Data
23 0.007570 192.168.0.29 → 172.18.0.2 TLSv1.3 336 Continuation Data
24 0.007575 10.0.0.3 → 10.0.0.2 TLSv1.3 336 Continuation Data
25 0.007638 10.0.0.2 → 10.0.0.3 OpenVPN 98 MessageType: P_ACK_V1
26 0.007646 172.18.0.2 → 192.168.0.29 OpenVPN 98 MessageType: P_ACK_V1
27 0.008507 10.0.0.2 → 10.0.0.3 TLSv1.3 260 Application Data, Application Data
28 0.008516 172.18.0.2 → 192.168.0.29 TLSv1.3 260 Application Data, Application Data
29 0.008762 192.168.0.29 → 172.18.0.2 OpenVPN 114 MessageType: P_ACK_V1
30 0.008768 10.0.0.3 → 10.0.0.2 OpenVPN 114 MessageType: P_ACK_V1
31 0.008922 10.0.0.2 → 10.0.0.3 TLSv1.3 343 Application Data
32 0.008930 172.18.0.2 → 192.168.0.29 TLSv1.3 343 Application Data
33 0.009260 192.168.0.29 → 172.18.0.2 OpenVPN 118 MessageType: P_ACK_V1
34 0.009266 10.0.0.3 → 10.0.0.2 OpenVPN 118 MessageType: P_ACK_V1
35 1.135729 192.168.0.29 → 172.18.0.2 TLSv1.3 149 Application Data
36 1.135745 10.0.0.3 → 10.0.0.2 TLSv1.3 149 Application Data
37 1.136230 10.0.0.2 → 10.0.0.3 OpenVPN 98 MessageType: P_ACK_V1
38 1.136246 172.18.0.2 → 192.168.0.29 OpenVPN 98 MessageType: P_ACK_V1
39 1.136320 10.0.0.2 → 10.0.0.3 TLSv1.3 317 Application Data
40 1.136325 172.18.0.2 → 192.168.0.29 TLSv1.3 317 Application Data
41 1.137945 192.168.0.29 → 172.18.0.2 OpenVPN 122 MessageType: P_ACK_V1
42 1.137954 10.0.0.3 → 10.0.0.2 OpenVPN 122 MessageType: P_ACK_V1
43 1.137981 192.168.0.29 → 172.18.0.2 OpenVPN 121 MessageType: P_DATA_V2
44 1.137984 10.0.0.3 → 10.0.0.2 OpenVPN 121 MessageType: P_DATA_V2
45 5.199670 192.168.0.29 → 172.18.0.2 OpenVPN 121 MessageType: P_DATA_V2
[2025-10-28 19:59:21] === Firewall Statistics ===
Chain INPUT (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
12 1128 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
1 84 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
1 84 ACCEPT icmp -- eth1 * 0.0.0.0/0 0.0.0.0/0 icmptype 8
0 0 LOG udp -- eth0 * 0.0.0.0/0 0.0.0.0/0 udp dpt:1194 LOG flags 0 level 4 prefix "VPN-IN: "
0 0 ACCEPT udp -- eth0 * 0.0.0.0/0 0.0.0.0/0 udp dpt:1194
0 0 LOG all -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4 prefix "DROP-IN: "
0 0 DROP all -- * * 0.0.0.0/0 0.0.0.0/0
Chain FORWARD (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
112 14795 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
1 70 LOG udp -- eth0 eth1 0.0.0.0/0 10.0.0.2 udp dpt:1194 LOG flags 0 level 4 prefix "FWD-TO-VPN: "
1 70 ACCEPT udp -- eth0 eth1 0.0.0.0/0 10.0.0.2 udp dpt:1194
0 0 LOG all -- eth1 eth0 10.0.0.0/24 0.0.0.0/0 LOG flags 0 level 4 prefix "FWD-OUT: "
0 0 ACCEPT all -- eth1 eth0 10.0.0.0/24 0.0.0.0/0
0 0 LOG all -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4 prefix "DROP-FWD: "
0 0 DROP all -- * * 0.0.0.0/0 0.0.0.0/0
Chain OUTPUT (policy ACCEPT 14 packets, 1296 bytes)
pkts bytes target prot opt in out source destination
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
1 70 LOG udp -- eth0 * 0.0.0.0/0 0.0.0.0/0 udp dpt:1194 LOG flags 0 level 4 prefix "DNAT: "
1 70 DNAT udp -- eth0 * 0.0.0.0/0 0.0.0.0/0 udp dpt:1194 to:10.0.0.2:1194
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 6 packets, 480 bytes)
pkts bytes target prot opt in out source destination
Chain POSTROUTING (policy ACCEPT 6 packets, 480 bytes)
pkts bytes target prot opt in out source destination
1 70 MASQUERADE udp -- * eth1 0.0.0.0/0 10.0.0.2 udp dpt:1194
0 0 MASQUERADE all -- * eth0 10.0.0.0/24 0.0.0.0/0
Chain DOCKER_OUTPUT (0 references)
pkts bytes target prot opt in out source destination
Chain DOCKER_POSTROUTING (0 references)
pkts bytes target prot opt in out source destination
======================================