From 22ea468567fa30c2419df1ec146432feba014262 Mon Sep 17 00:00:00 2001 From: Franzi Funke-Kaiser Date: Sun, 29 Mar 2026 15:01:09 +0200 Subject: [PATCH 1/9] add openwrt dockerfile --- software/open-wrt/Dockerfile | 18 ++++++++++++++++++ software/open-wrt/docker-compose.yml | 7 +++++++ 2 files changed, 25 insertions(+) create mode 100644 software/open-wrt/Dockerfile create mode 100644 software/open-wrt/docker-compose.yml diff --git a/software/open-wrt/Dockerfile b/software/open-wrt/Dockerfile new file mode 100644 index 00000000..25fcf4d1 --- /dev/null +++ b/software/open-wrt/Dockerfile @@ -0,0 +1,18 @@ +FROM debian:bookworm-slim + +RUN apt-get update && apt-get install -y \ + qemu-system-x86 \ + wget && rm -rf /var/lib/apt/lists/* + +WORKDIR /openwrt + +RUN wget -q https://downloads.openwrt.org/releases/24.10.5/targets/x86/64/openwrt-24.10.5-x86-64-generic-ext4-combined.img.gz \ + && gunzip openwrt-24.10.5-x86-64-generic-ext4-combined.img.gz; \ + EC=$?; [ $EC -eq 0 ] || [ $EC -eq 2 ] \ + && mv openwrt-24.10.5-x86-64-generic-ext4-combined.img openwrt.img + +CMD ["qemu-system-x86_64", \ + "-nographic", \ + "-m", "256M", \ + "-drive", "file=openwrt.img,format=raw", \ + "-serial", "mon:stdio"] \ No newline at end of file diff --git a/software/open-wrt/docker-compose.yml b/software/open-wrt/docker-compose.yml new file mode 100644 index 00000000..2997a506 --- /dev/null +++ b/software/open-wrt/docker-compose.yml @@ -0,0 +1,7 @@ +services: + openwrt: + build: . + image: cybics-openwrt-test + stdin_open: true + tty: true + \ No newline at end of file From a960163127b4d99a4f8f609369150d7d6fb36d96 Mon Sep 17 00:00:00 2001 From: Franzi Funke-Kaiser Date: Sun, 29 Mar 2026 15:47:00 +0200 Subject: [PATCH 2/9] add tap interfaces --- software/open-wrt/Dockerfile | 19 +++++++++++------ software/open-wrt/docker-compose.yml | 32 +++++++++++++++++++++++++++- software/open-wrt/start.sh | 20 +++++++++++++++++ 3 files changed, 64 insertions(+), 7 deletions(-) create mode 100644 software/open-wrt/start.sh diff --git a/software/open-wrt/Dockerfile b/software/open-wrt/Dockerfile index 25fcf4d1..c857b17c 100644 --- a/software/open-wrt/Dockerfile +++ b/software/open-wrt/Dockerfile @@ -2,7 +2,9 @@ FROM debian:bookworm-slim RUN apt-get update && apt-get install -y \ qemu-system-x86 \ - wget && rm -rf /var/lib/apt/lists/* + wget \ + iproute2 \ + && rm -rf /var/lib/apt/lists/* WORKDIR /openwrt @@ -11,8 +13,13 @@ RUN wget -q https://downloads.openwrt.org/releases/24.10.5/targets/x86/64/openwr EC=$?; [ $EC -eq 0 ] || [ $EC -eq 2 ] \ && mv openwrt-24.10.5-x86-64-generic-ext4-combined.img openwrt.img -CMD ["qemu-system-x86_64", \ - "-nographic", \ - "-m", "256M", \ - "-drive", "file=openwrt.img,format=raw", \ - "-serial", "mon:stdio"] \ No newline at end of file +# CMD ["qemu-system-x86_64", \ +# "-nographic", \ +# "-m", "256M", \ +# "-drive", "file=openwrt.img,format=raw", \ +# "-serial", "mon:stdio"] + +COPY start.sh start.sh +RUN chmod +x start.sh + +CMD ["/openwrt/start.sh"] \ No newline at end of file diff --git a/software/open-wrt/docker-compose.yml b/software/open-wrt/docker-compose.yml index 2997a506..9aba60fb 100644 --- a/software/open-wrt/docker-compose.yml +++ b/software/open-wrt/docker-compose.yml @@ -4,4 +4,34 @@ services: image: cybics-openwrt-test stdin_open: true tty: true - \ No newline at end of file + cap_add: + - NET_ADMIN + devices: + - /dev/net/tun:/dev/net/tun + networks: + ext_net: + ipv4_address: 172.20.0.2 + int_net: + ipv4_address: 172.21.0.2 + test: + image: alpine + command: sleep infinity + networks: + ext_net: + ipv4_address: 172.20.0.3 + +networks: + ext_net: + driver: bridge + driver_opts: + com.docker.network.bridge.name: br-ext + ipam: + config: + - subnet: 172.20.0.0/24 + int_net: + driver: bridge + driver_opts: + com.docker.network.bridge.name: br-int + ipam: + config: + - subnet: 172.21.0.0/24 \ No newline at end of file diff --git a/software/open-wrt/start.sh b/software/open-wrt/start.sh new file mode 100644 index 00000000..f5d6f5c6 --- /dev/null +++ b/software/open-wrt/start.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +ip tuntap add dev tap0 mode tap +ip tuntap add dev tap1 mode tap + +ip link set tap0 master br-ext +ip link set tap1 master br-int + +ip link set tap0 up +ip link set tap1 up + +exec qemu-system-x86_64 \ + -nographic \ + -m 256M \ + -drive file=openwrt.img,format=raw \ + -serial mon:stdio \ + -netdev tap,id=n0,ifname=tap0,script=no,downscript=no \ + -device e1000,netdev=n0 \ + -netdev tap,id=n1,ifname=tap1,script=no,downscript=no \ + -device e1000,netdev=n1 \ No newline at end of file From 196dc173bd8723d8def4bd99b6531e8b26218c49 Mon Sep 17 00:00:00 2001 From: franzifk Date: Tue, 31 Mar 2026 14:14:34 +0200 Subject: [PATCH 3/9] =?UTF-8?q?draft:=20aktueller=20stand=20mit=20qemu=20(?= =?UTF-8?q?b=C3=A4=C3=A4=C3=A4h)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- software/open-wrt/99-wan-config | 6 ++++++ software/open-wrt/Dockerfile | 11 ++++++----- software/open-wrt/docker-compose.yml | 2 ++ software/open-wrt/start.sh | 6 ++++-- 4 files changed, 18 insertions(+), 7 deletions(-) create mode 100644 software/open-wrt/99-wan-config diff --git a/software/open-wrt/99-wan-config b/software/open-wrt/99-wan-config new file mode 100644 index 00000000..4bc086c7 --- /dev/null +++ b/software/open-wrt/99-wan-config @@ -0,0 +1,6 @@ +#!/bin/sh +uci set network.wan.proto='static' +uci set network.wan.ipaddr='172.20.0.2' +uci set network.wan.netmask='255.255.255.0' +uci set network.wan.gateway='172.20.0.1' +uci commit network \ No newline at end of file diff --git a/software/open-wrt/Dockerfile b/software/open-wrt/Dockerfile index c857b17c..db98b6be 100644 --- a/software/open-wrt/Dockerfile +++ b/software/open-wrt/Dockerfile @@ -13,11 +13,12 @@ RUN wget -q https://downloads.openwrt.org/releases/24.10.5/targets/x86/64/openwr EC=$?; [ $EC -eq 0 ] || [ $EC -eq 2 ] \ && mv openwrt-24.10.5-x86-64-generic-ext4-combined.img openwrt.img -# CMD ["qemu-system-x86_64", \ -# "-nographic", \ -# "-m", "256M", \ -# "-drive", "file=openwrt.img,format=raw", \ -# "-serial", "mon:stdio"] +COPY 99-wan-config /tmp/99-wan-config + +RUN dd if=openwrt.img of=partition2.img bs=512 skip=33792 2>/dev/null \ + && printf 'cd /etc/uci-defaults\nwrite /tmp/99-wan-config 99-wan-config\n' | debugfs -w partition2.img \ + && dd if=partition2.img of=openwrt.img bs=512 seek=33792 conv=notrunc 2>/dev/null \ + && rm partition2.img COPY start.sh start.sh RUN chmod +x start.sh diff --git a/software/open-wrt/docker-compose.yml b/software/open-wrt/docker-compose.yml index 9aba60fb..7527026c 100644 --- a/software/open-wrt/docker-compose.yml +++ b/software/open-wrt/docker-compose.yml @@ -1,5 +1,7 @@ services: openwrt: + ports: + - "2222:2222" build: . image: cybics-openwrt-test stdin_open: true diff --git a/software/open-wrt/start.sh b/software/open-wrt/start.sh index f5d6f5c6..69ea191d 100644 --- a/software/open-wrt/start.sh +++ b/software/open-wrt/start.sh @@ -11,10 +11,12 @@ ip link set tap1 up exec qemu-system-x86_64 \ -nographic \ - -m 256M \ + -m 128M \ -drive file=openwrt.img,format=raw \ -serial mon:stdio \ -netdev tap,id=n0,ifname=tap0,script=no,downscript=no \ -device e1000,netdev=n0 \ -netdev tap,id=n1,ifname=tap1,script=no,downscript=no \ - -device e1000,netdev=n1 \ No newline at end of file + -device e1000,netdev=n1 \ + -netdev user,id=n2,hostfwd=tcp::2222-:22 \ + -device e1000,netdev=n2 \ No newline at end of file From 2f91e3bd3152d22077cf69231cb9d371b4fe827f Mon Sep 17 00:00:00 2001 From: franzifk Date: Wed, 1 Apr 2026 08:17:44 +0200 Subject: [PATCH 4/9] per ssh erreichbar --- software/open-wrt/99-wan-config | 13 ++++++++- software/open-wrt/Dockerfile | 31 +++++++++++++++----- software/open-wrt/start.sh | 51 ++++++++++++++++++++++++--------- 3 files changed, 74 insertions(+), 21 deletions(-) diff --git a/software/open-wrt/99-wan-config b/software/open-wrt/99-wan-config index 4bc086c7..c07688bf 100644 --- a/software/open-wrt/99-wan-config +++ b/software/open-wrt/99-wan-config @@ -3,4 +3,15 @@ uci set network.wan.proto='static' uci set network.wan.ipaddr='172.20.0.2' uci set network.wan.netmask='255.255.255.0' uci set network.wan.gateway='172.20.0.1' -uci commit network \ No newline at end of file +uci commit network + +# eth2 (QEMU user-netdev) konfigurieren +uci set network.qemu=interface +uci set network.qemu.ifname='eth2' +uci set network.qemu.proto='dhcp' +uci commit network + +uci add_list firewall.@zone[0].network='qemu' +uci commit firewall + +(echo "password"; echo "password") | passwd root \ No newline at end of file diff --git a/software/open-wrt/Dockerfile b/software/open-wrt/Dockerfile index db98b6be..188f8563 100644 --- a/software/open-wrt/Dockerfile +++ b/software/open-wrt/Dockerfile @@ -1,23 +1,40 @@ FROM debian:bookworm-slim RUN apt-get update && apt-get install -y \ - qemu-system-x86 \ wget \ iproute2 \ + e2tools \ + python3 \ + && ARCH=$(dpkg --print-architecture) \ + && if [ "$ARCH" = "arm64" ]; then \ + apt-get install -y qemu-system-arm qemu-efi-aarch64; \ + else \ + apt-get install -y qemu-system-x86; \ + fi \ && rm -rf /var/lib/apt/lists/* WORKDIR /openwrt -RUN wget -q https://downloads.openwrt.org/releases/24.10.5/targets/x86/64/openwrt-24.10.5-x86-64-generic-ext4-combined.img.gz \ - && gunzip openwrt-24.10.5-x86-64-generic-ext4-combined.img.gz; \ - EC=$?; [ $EC -eq 0 ] || [ $EC -eq 2 ] \ - && mv openwrt-24.10.5-x86-64-generic-ext4-combined.img openwrt.img +RUN ARCH=$(dpkg --print-architecture) \ + && if [ "$ARCH" = "arm64" ]; then \ + wget -q https://downloads.openwrt.org/releases/24.10.5/targets/armsr/armv8/openwrt-24.10.5-armsr-armv8-generic-ext4-combined-efi.img.gz \ + && gunzip openwrt-24.10.5-armsr-armv8-generic-ext4-combined-efi.img.gz; \ + EC=$?; [ $EC -eq 0 ] || [ $EC -eq 2 ] \ + && mv openwrt-24.10.5-armsr-armv8-generic-ext4-combined-efi.img openwrt.img; \ + else \ + wget -q https://downloads.openwrt.org/releases/24.10.5/targets/x86/64/openwrt-24.10.5-x86-64-generic-ext4-combined.img.gz \ + && gunzip openwrt-24.10.5-x86-64-generic-ext4-combined.img.gz; \ + EC=$?; [ $EC -eq 0 ] || [ $EC -eq 2 ] \ + && mv openwrt-24.10.5-x86-64-generic-ext4-combined.img openwrt.img; \ + fi COPY 99-wan-config /tmp/99-wan-config -RUN dd if=openwrt.img of=partition2.img bs=512 skip=33792 2>/dev/null \ +RUN ARCH=$(dpkg --print-architecture) \ + && if [ "$ARCH" = "arm64" ]; then SKIP=262656; else SKIP=33792; fi \ + && dd if=openwrt.img of=partition2.img bs=512 skip=$SKIP 2>/dev/null \ && printf 'cd /etc/uci-defaults\nwrite /tmp/99-wan-config 99-wan-config\n' | debugfs -w partition2.img \ - && dd if=partition2.img of=openwrt.img bs=512 seek=33792 conv=notrunc 2>/dev/null \ + && dd if=partition2.img of=openwrt.img bs=512 seek=$SKIP conv=notrunc 2>/dev/null \ && rm partition2.img COPY start.sh start.sh diff --git a/software/open-wrt/start.sh b/software/open-wrt/start.sh index 69ea191d..2a7b8bb1 100644 --- a/software/open-wrt/start.sh +++ b/software/open-wrt/start.sh @@ -3,20 +3,45 @@ ip tuntap add dev tap0 mode tap ip tuntap add dev tap1 mode tap -ip link set tap0 master br-ext -ip link set tap1 master br-int +# Bridges nur auf Linux verfügbar +if ip link show br-ext > /dev/null 2>&1; then + ip link set tap0 master br-ext + ip link set tap1 master br-int + echo "TAP bridging enabled" +else + echo "Warning: br-ext/br-int not available (macOS Docker Desktop), TAP bridging disabled" +fi ip link set tap0 up ip link set tap1 up -exec qemu-system-x86_64 \ - -nographic \ - -m 128M \ - -drive file=openwrt.img,format=raw \ - -serial mon:stdio \ - -netdev tap,id=n0,ifname=tap0,script=no,downscript=no \ - -device e1000,netdev=n0 \ - -netdev tap,id=n1,ifname=tap1,script=no,downscript=no \ - -device e1000,netdev=n1 \ - -netdev user,id=n2,hostfwd=tcp::2222-:22 \ - -device e1000,netdev=n2 \ No newline at end of file +ARCH=$(uname -m) + +if [ "$ARCH" = "aarch64" ]; then + exec qemu-system-aarch64 \ + -nographic \ + -machine virt \ + -cpu cortex-a57 \ + -m 256M \ + -drive file=openwrt.img,format=raw \ + -bios /usr/share/qemu-efi-aarch64/QEMU_EFI.fd \ + -serial mon:stdio \ + -netdev tap,id=n0,ifname=tap0,script=no,downscript=no \ + -device virtio-net-pci,netdev=n0 \ + -netdev tap,id=n1,ifname=tap1,script=no,downscript=no \ + -device virtio-net-pci,netdev=n1 \ + -netdev user,id=n2,hostfwd=tcp::2222-:22 \ + -device virtio-net-pci,netdev=n2 +else + exec qemu-system-x86_64 \ + -nographic \ + -m 128M \ + -drive file=openwrt.img,format=raw \ + -serial mon:stdio \ + -netdev tap,id=n0,ifname=tap0,script=no,downscript=no \ + -device e1000,netdev=n0 \ + -netdev tap,id=n1,ifname=tap1,script=no,downscript=no \ + -device e1000,netdev=n1 \ + -netdev user,id=n2,hostfwd=tcp::2222-:22 \ + -device e1000,netdev=n2 +fi \ No newline at end of file From 6c1fb9b503f6e399cabec98a83e7590cb0bb9213 Mon Sep 17 00:00:00 2001 From: franzifk Date: Sat, 11 Apr 2026 14:40:27 +0200 Subject: [PATCH 5/9] change int network name --- software/open-wrt/docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/software/open-wrt/docker-compose.yml b/software/open-wrt/docker-compose.yml index 7527026c..7db8cc75 100644 --- a/software/open-wrt/docker-compose.yml +++ b/software/open-wrt/docker-compose.yml @@ -13,7 +13,7 @@ services: networks: ext_net: ipv4_address: 172.20.0.2 - int_net: + virt-cybics: ipv4_address: 172.21.0.2 test: image: alpine @@ -30,7 +30,7 @@ networks: ipam: config: - subnet: 172.20.0.0/24 - int_net: + virt-cybics: driver: bridge driver_opts: com.docker.network.bridge.name: br-int From c67972e7f4c5e2b7df32057797fe7bb9315b47b8 Mon Sep 17 00:00:00 2001 From: franzifk Date: Sun, 12 Apr 2026 12:01:55 +0200 Subject: [PATCH 6/9] debug commit --- .claude/worktrees/musing-swirles | 1 + software/open-wrt/99-wan-config | 30 ++++++++++--- software/open-wrt/docker-compose.test.yml | 51 +++++++++++++++++++++++ software/open-wrt/docker-compose.yml | 31 +++++--------- software/open-wrt/run-test.sh | 24 +++++++++++ software/open-wrt/start-challenge-07.sh | 35 ++++++++++++++++ software/open-wrt/start.sh | 30 +++++++++---- software/open-wrt/stop-challenge-07.sh | 31 ++++++++++++++ 8 files changed, 199 insertions(+), 34 deletions(-) create mode 160000 .claude/worktrees/musing-swirles create mode 100644 software/open-wrt/docker-compose.test.yml create mode 100755 software/open-wrt/run-test.sh create mode 100755 software/open-wrt/start-challenge-07.sh create mode 100755 software/open-wrt/stop-challenge-07.sh diff --git a/.claude/worktrees/musing-swirles b/.claude/worktrees/musing-swirles new file mode 160000 index 00000000..7266fa28 --- /dev/null +++ b/.claude/worktrees/musing-swirles @@ -0,0 +1 @@ +Subproject commit 7266fa28dc6a167cdc171ffa4e71959865bf8b44 diff --git a/software/open-wrt/99-wan-config b/software/open-wrt/99-wan-config index c07688bf..d834b1f4 100644 --- a/software/open-wrt/99-wan-config +++ b/software/open-wrt/99-wan-config @@ -1,17 +1,37 @@ #!/bin/sh + +# 1. OpenWrt Default-Müll rigoros killen! +uci delete network.lan +uci delete network.wan +uci delete network.wan6 + +# 2. WAN sauber neu aufbauen (eth0) +uci set network.wan=interface +uci set network.wan.device='eth0' uci set network.wan.proto='static' -uci set network.wan.ipaddr='172.20.0.2' +uci set network.wan.ipaddr='172.19.0.2' uci set network.wan.netmask='255.255.255.0' -uci set network.wan.gateway='172.20.0.1' -uci commit network -# eth2 (QEMU user-netdev) konfigurieren +# 3. LAN sauber neu aufbauen (eth1) +uci set network.lan=interface +uci set network.lan.device='eth1' +uci set network.lan.proto='static' +uci set network.lan.ipaddr='172.18.0.254' +uci set network.lan.netmask='255.255.255.0' + +# 4. QEMU SSH-Interface (eth2) uci set network.qemu=interface -uci set network.qemu.ifname='eth2' +uci set network.qemu.device='eth2' uci set network.qemu.proto='dhcp' + uci commit network +# Firewall für SSH und Durchleitung öffnen uci add_list firewall.@zone[0].network='qemu' +uci set firewall.@zone[0].input='ACCEPT' +uci set firewall.@zone[0].forward='ACCEPT' +uci set firewall.@zone[1].input='ACCEPT' +uci set firewall.@zone[1].forward='ACCEPT' uci commit firewall (echo "password"; echo "password") | passwd root \ No newline at end of file diff --git a/software/open-wrt/docker-compose.test.yml b/software/open-wrt/docker-compose.test.yml new file mode 100644 index 00000000..e0958ada --- /dev/null +++ b/software/open-wrt/docker-compose.test.yml @@ -0,0 +1,51 @@ +services: + # Der Router, den wir testen wollen + router-test: + image: cybics-openwrt-router:test + build: + context: . + cap_add: + - NET_ADMIN + devices: + - /dev/net/tun:/dev/net/tun + ports: + - "2222:2222" + networks: + test_ext: + ipv4_address: 172.19.0.2 + test_int: + ipv4_address: 172.18.0.254 + + # Ein Test-Client im "Internet" (WAN) + wan-probe: + image: alpine + command: sh -c "ip route add 172.18.0.0/24 via 172.19.0.2 && sleep infinity" + cap_add: + - NET_ADMIN + networks: + test_ext: + ipv4_address: 172.19.0.100 + depends_on: + - router-test + + # Ein Test-Server im "ICS-Netz" (LAN) + lan-probe: + image: alpine + command: sleep infinity + networks: + test_int: + ipv4_address: 172.18.0.10 + depends_on: + - router-test + +networks: + test_ext: + driver: bridge + ipam: + config: + - subnet: 172.19.0.0/24 + test_int: + driver: bridge + ipam: + config: + - subnet: 172.18.0.0/24 \ No newline at end of file diff --git a/software/open-wrt/docker-compose.yml b/software/open-wrt/docker-compose.yml index 7db8cc75..d8c315b8 100644 --- a/software/open-wrt/docker-compose.yml +++ b/software/open-wrt/docker-compose.yml @@ -1,9 +1,8 @@ services: - openwrt: - ports: - - "2222:2222" - build: . - image: cybics-openwrt-test + router: + image: cybics-openwrt-router:${CYBICS_VERSION:-latest} + build: + context: . stdin_open: true tty: true cap_add: @@ -12,28 +11,18 @@ services: - /dev/net/tun:/dev/net/tun networks: ext_net: - ipv4_address: 172.20.0.2 + ipv4_address: 172.19.0.2 virt-cybics: - ipv4_address: 172.21.0.2 - test: - image: alpine - command: sleep infinity - networks: - ext_net: - ipv4_address: 172.20.0.3 + ipv4_address: 172.18.0.254 networks: ext_net: driver: bridge driver_opts: - com.docker.network.bridge.name: br-ext + com.docker.network.bridge.name: cybics-ext-net ipam: config: - - subnet: 172.20.0.0/24 + - subnet: 172.19.0.0/24 virt-cybics: - driver: bridge - driver_opts: - com.docker.network.bridge.name: br-int - ipam: - config: - - subnet: 172.21.0.0/24 \ No newline at end of file + external: true + name: virtual_virt-cybics diff --git a/software/open-wrt/run-test.sh b/software/open-wrt/run-test.sh new file mode 100755 index 00000000..09842086 --- /dev/null +++ b/software/open-wrt/run-test.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# Stoppe alte Tests +docker compose -f docker-compose.test.yml down + +echo "[*] Baue Router-Image..." +docker compose -f docker-compose.test.yml build --no-cache + +echo "[*] Starte Test-Umgebung..." +docker compose -f docker-compose.test.yml up -d + +echo "[*] Warte 60 Sekunden auf OpenWrt Boot..." +sleep 60 + +echo "[*] TEST 1: Ping von WAN-Probe zum Router (WAN-Interface)..." +docker exec open-wrt-wan-probe-1 ping -c 3 172.19.0.2 + +echo "[*] TEST 2: Ping von WAN-Probe durch den Router zur LAN-Probe..." +docker exec open-wrt-wan-probe-1 ping -c 3 172.18.0.10 + +if [ $? -eq 0 ]; then + echo -e "\n[+] ERFOLG: Der Router leitet Traffic korrekt weiter!" +else + echo -e "\n[-] FEHLER: Routing funktioniert nicht. Prüfe 'docker logs router-test'." +fi \ No newline at end of file diff --git a/software/open-wrt/start-challenge-07.sh b/software/open-wrt/start-challenge-07.sh new file mode 100755 index 00000000..1f71a680 --- /dev/null +++ b/software/open-wrt/start-challenge-07.sh @@ -0,0 +1,35 @@ +#!/bin/bash +set -e +$ROUTER_NET="challenge07_ext_net" + + +echo "[*] Starting Challenge 07: Router Pivoting..." + +# Router starten +echo "[*] Starting router container..." +docker compose -p challenge07 -f docker-compose.yml up -d + +# Attack-Machine Container finden +ATTACK_CONTAINER=$(docker ps --format '{{.Names}}' | grep 'attack-machine' | head -1) + +if [ -z "$ATTACK_CONTAINER" ]; then + echo "[!] Error: attack-machine container not found. Is the base environment running?" + exit 1 +fi + +echo "[*] Found attack-machine: $ATTACK_CONTAINER" + +# Attack-Machine vom internen Netz trennen +echo "[*] Disconnecting attack-machine from virt-cybics..." +docker network disconnect virtual_virt-cybics "$ATTACK_CONTAINER" + +# Attack-Machine mit externem Netz verbinden +echo "[*] Connecting attack-machine to ext_net (172.19.0.100)..." +docker network connect --ip 172.19.0.100 $ROUTER_NET "$ATTACK_CONTAINER" + +echo "" +echo "[+] Challenge 07 active." +echo "[+] Attack machine : $ATTACK_CONTAINER @ 172.19.0.100 (ext_net)" +echo "[+] Router WAN : 172.19.0.2 (ext_net)" +echo "[+] Router LAN : 172.18.0.254 (virt-cybics)" +echo "[+] Pivot through the router to reach the ICS network." diff --git a/software/open-wrt/start.sh b/software/open-wrt/start.sh index 2a7b8bb1..be56f0a9 100644 --- a/software/open-wrt/start.sh +++ b/software/open-wrt/start.sh @@ -3,18 +3,32 @@ ip tuntap add dev tap0 mode tap ip tuntap add dev tap1 mode tap -# Bridges nur auf Linux verfügbar -if ip link show br-ext > /dev/null 2>&1; then - ip link set tap0 master br-ext - ip link set tap1 master br-int - echo "TAP bridging enabled" -else - echo "Warning: br-ext/br-int not available (macOS Docker Desktop), TAP bridging disabled" -fi +# Container-namespace Bridges erstellen (OS-unabhängig, kein Host-Bridge-Zugriff nötig) +ip link add br-ext type bridge +ip link add br-int type bridge + +# IPs der Docker-Interfaces entfernen (Bridge übernimmt L2-Forwarding) +ip addr flush dev eth0 +ip addr flush dev eth1 + +# Docker-Interfaces an Bridges binden +ip link set eth0 master br-ext +ip link set eth1 master br-int +# QEMU-TAP-Devices an Bridges binden +ip link set tap0 master br-ext +ip link set tap1 master br-int + +# Alle Interfaces hochbringen +ip link set br-ext up +ip link set br-int up +ip link set eth0 up +ip link set eth1 up ip link set tap0 up ip link set tap1 up +echo "TAP bridging enabled (container namespace)" + ARCH=$(uname -m) if [ "$ARCH" = "aarch64" ]; then diff --git a/software/open-wrt/stop-challenge-07.sh b/software/open-wrt/stop-challenge-07.sh new file mode 100755 index 00000000..69c77070 --- /dev/null +++ b/software/open-wrt/stop-challenge-07.sh @@ -0,0 +1,31 @@ +#!/bin/bash +set -e +$ROUTER_NET="challenge07_ext_net" + + +echo "[*] Stopping Challenge 07: Router Pivoting..." + +# Attack-Machine Container finden +ATTACK_CONTAINER=$(docker ps --format '{{.Names}}' | grep 'attack-machine' | head -1) + +if [ -z "$ATTACK_CONTAINER" ]; then + echo "[!] Warning: attack-machine container not found, skipping network rollback." +else + echo "[*] Found attack-machine: $ATTACK_CONTAINER" + + # Attack-Machine wieder mit internem Netz verbinden + echo "[*] Reconnecting attack-machine to virt-cybics (172.18.0.100)..." + docker network connect --ip 172.18.0.100 virtual_virt-cybics "$ATTACK_CONTAINER" + + # Attack-Machine vom externen Netz trennen + echo "[*] Disconnecting attack-machine from ext_net..." + docker network disconnect $ROUTER_NET "$ATTACK_CONTAINER" +fi + +# Router stoppen +echo "[*] Stopping router container..." +docker compose -p challenge07 -f docker-compose.yml down + +echo "" +echo "[+] Challenge 07 stopped." +echo "[+] Attack machine restored to virt-cybics @ 172.18.0.100" From 0a3bb97027d7fe60e08a33174cf6017dac29544a Mon Sep 17 00:00:00 2001 From: franzifk Date: Mon, 13 Apr 2026 09:50:05 +0200 Subject: [PATCH 7/9] add router test --- software/open-wrt/test-router.sh | 183 +++++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100755 software/open-wrt/test-router.sh diff --git a/software/open-wrt/test-router.sh b/software/open-wrt/test-router.sh new file mode 100755 index 00000000..511c6000 --- /dev/null +++ b/software/open-wrt/test-router.sh @@ -0,0 +1,183 @@ +#!/bin/bash +# test-router.sh — Build & test CybICS OpenWrt router +# Baut mit --no-cache, startet den Stack, prüft SSH-Erreichbarkeit + +COMPOSE_FILE="docker-compose.yml" +SSH_PORT=2222 +SSH_HOST="127.0.0.1" +MAX_WAIT=120 +POLL_INTERVAL=5 + +GREEN='\033[0;32m' +RED='\033[0;31m' +YELLOW='\033[1;33m' +NC='\033[0m' + +passed=0 +failed=0 + +log() { echo -e "${YELLOW}[TEST]${NC} $*"; } +pass() { echo -e "${GREEN}[PASS]${NC} $*"; ((passed++)); } +fail() { echo -e "${RED}[FAIL]${NC} $*"; ((failed++)); } + +cleanup() { + log "Räume auf..." + docker compose -f "$COMPOSE_FILE" down --timeout 5 2>/dev/null || true +} +trap cleanup EXIT + +# ─── 1. Build ─────────────────────────────────────────────── +log "Starte Build (--no-cache)..." +docker compose -f "$COMPOSE_FILE" build --no-cache +BUILD_RC=$? +if [ $BUILD_RC -eq 0 ]; then + pass "Docker Build erfolgreich" +else + fail "Docker Build fehlgeschlagen (Exit Code: $BUILD_RC)" + exit 1 +fi + +# ─── 2. Stack starten ────────────────────────────────────── +log "Starte Stack..." +UP_OUTPUT=$(docker compose -f "$COMPOSE_FILE" up -d 2>&1) +UP_RC=$? +if [ $UP_RC -ne 0 ]; then + fail "Stack konnte nicht gestartet werden (Exit Code: $UP_RC)" + echo "$UP_OUTPUT" + echo "" + log "Tipp: Versuch 'docker network prune -f' und dann nochmal." + exit 1 +fi + +sleep 3 + +# Container-Status prüfen +CONTAINER_STATUS=$(docker compose -f "$COMPOSE_FILE" ps --format "table {{.Name}}\t{{.Status}}" 2>&1) +echo "$CONTAINER_STATUS" + +if docker compose -f "$COMPOSE_FILE" ps --status running --format "{{.Name}}" 2>/dev/null | grep -q "openwrt"; then + pass "OpenWrt-Container läuft" +else + fail "OpenWrt-Container läuft nicht" + log "Container-Logs:" + docker compose -f "$COMPOSE_FILE" logs --tail 30 + exit 1 +fi + +# ─── 3. Warten bis SSH erreichbar ─────────────────────────── +log "Warte auf SSH-Port $SSH_PORT (max ${MAX_WAIT}s)..." +elapsed=0 +ssh_ok=false + +while [ $elapsed -lt $MAX_WAIT ]; do + if nc -z -w2 "$SSH_HOST" "$SSH_PORT" 2>/dev/null; then + ssh_ok=true + break + fi + sleep $POLL_INTERVAL + elapsed=$((elapsed + POLL_INTERVAL)) + printf "." +done +echo "" + +if $ssh_ok; then + pass "SSH-Port $SSH_PORT erreichbar nach ${elapsed}s" +else + fail "SSH-Port $SSH_PORT nicht erreichbar nach ${MAX_WAIT}s" + log "Container-Logs (letzte 50 Zeilen):" + docker compose -f "$COMPOSE_FILE" logs --tail 50 + exit 1 +fi + +# Warten bis SSH-Banner kommt (Daemon wirklich bereit) +log "Warte auf SSH-Banner (max 60s)..." +banner_wait=0 +banner_ok=false +while [ $banner_wait -lt 60 ]; do + BANNER=$(echo "" | nc -w3 "$SSH_HOST" "$SSH_PORT" 2>/dev/null || true) + if echo "$BANNER" | grep -qi "SSH"; then + banner_ok=true + break + fi + sleep 5 + banner_wait=$((banner_wait + 5)) + printf "." +done +echo "" + +if $banner_ok; then + pass "SSH-Daemon bereit nach $((elapsed + banner_wait))s" + log "Warte 20s auf uci-defaults (Passwort setzen)..." + sleep 20 +else + fail "SSH-Banner nicht erhalten nach 60s" + log "Container-Logs (letzte 30 Zeilen):" + docker compose -f "$COMPOSE_FILE" logs --tail 30 +fi + +# ─── 4. SSH-Login testen ──────────────────────────────────── +log "Teste SSH-Login..." +SSH_OPTS="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=10" + +if ! command -v sshpass &>/dev/null; then + log "⚠ sshpass nicht installiert — überspringe Login-Tests" + log " Installieren mit: brew install hudochenkov/sshpass/sshpass" +else + SSH_CMD="sshpass -p password ssh $SSH_OPTS -p $SSH_PORT root@$SSH_HOST" + + LOGIN_OUTPUT=$($SSH_CMD "echo ok" 2>&1) + LOGIN_RC=$? + if [ $LOGIN_RC -eq 0 ] && echo "$LOGIN_OUTPUT" | grep -q "ok"; then + pass "SSH-Login mit root/password erfolgreich" + + # ─── 5. Netzwerk-Checks innerhalb OpenWrt ─────────── + log "Prüfe Netzwerk-Interfaces in OpenWrt..." + + iface_count=$($SSH_CMD "ip -o link show | grep -c 'eth'" 2>/dev/null || echo "0") + if [ "$iface_count" -ge 3 ]; then + pass "Alle 3 NICs vorhanden ($iface_count eth-Interfaces)" + else + fail "Nur $iface_count eth-Interface(s) gefunden, erwartet: 3" + $SSH_CMD "ip -o link show" 2>/dev/null || true + fi + + wan_check=$($SSH_CMD "ip -4 addr show | grep '172\.20\.0\.2'" 2>/dev/null || echo "") + if echo "$wan_check" | grep -q "172.20.0.2"; then + pass "WAN-IP korrekt: 172.20.0.2" + else + fail "WAN-IP 172.20.0.2 auf keinem Interface gefunden" + log "Alle IPs:" + $SSH_CMD "ip -4 addr show" 2>/dev/null || true + fi + + fw_check=$($SSH_CMD "uci show firewall.@zone[0].network" 2>/dev/null || echo "") + if echo "$fw_check" | grep -q "qemu"; then + pass "eth2 (qemu) ist in der LAN-Firewall-Zone" + else + fail "eth2 (qemu) fehlt in der Firewall-Zone" + log "Firewall-Config: $fw_check" + fi + else + fail "SSH-Login fehlgeschlagen (Exit Code: $LOGIN_RC)" + echo "$LOGIN_OUTPUT" + fi +fi + +# ─── 6. Ping vom test-Container zum Router ────────────────── +log "Teste Ping test→Router..." +PING_OUTPUT=$(docker compose -f "$COMPOSE_FILE" exec -T test ping -c 2 -W 3 172.20.0.2 2>&1) +PING_RC=$? +if [ $PING_RC -eq 0 ]; then + pass "test-Container kann Router (172.20.0.2) pingen" +else + fail "test-Container kann Router nicht erreichen" + echo "$PING_OUTPUT" +fi + +# ─── Ergebnis ──────────────────────────────────────────────── +echo "" +echo "═══════════════════════════════════════" +echo -e " Ergebnis: ${GREEN}${passed} bestanden${NC}, ${RED}${failed} fehlgeschlagen${NC}" +echo "═══════════════════════════════════════" + +[ $failed -eq 0 ] && exit 0 || exit 1 \ No newline at end of file From 6daeafe9a665f5d8ceb64e9b85e5a22927c13c75 Mon Sep 17 00:00:00 2001 From: franzifk Date: Mon, 13 Apr 2026 13:12:26 +0200 Subject: [PATCH 8/9] router jetzt gateway --- software/open-wrt/ctf-router.sh | 153 ++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100755 software/open-wrt/ctf-router.sh diff --git a/software/open-wrt/ctf-router.sh b/software/open-wrt/ctf-router.sh new file mode 100755 index 00000000..5f695306 --- /dev/null +++ b/software/open-wrt/ctf-router.sh @@ -0,0 +1,153 @@ +#!/bin/bash +# Startet/stoppt die CTF Router Challenge. +# Der OpenWrt-Router wird zwischen Angreifer und ICS-Netz gehängt. +# Usage: ./ctf-router.sh start|stop|status + +set -uo pipefail + +# --- Config --- +ROUTER_DIR="$(cd "$(dirname "$0")" && pwd)" +ROUTER_CONTAINER="open-wrt-openwrt-1" +INT_NET="virtual_virt-cybics" +EXT_NET="ext_ctf" +EXT_SUBNET="172.22.0.0/24" +EXT_GATEWAY="172.22.0.1" +ROUTER_INT_IP="172.18.0.50" +ROUTER_EXT_IP="172.22.0.2" +ATTACK_EXT_IP="172.22.0.100" +ATTACK_CONTAINER="attack-machine" + +find_container() { + docker ps --format '{{.Names}}' | grep -i "$1" | head -1 +} + +container_in_network() { + docker inspect "$1" --format '{{range $k,$v := .NetworkSettings.Networks}}{{$k}} {{end}}' 2>/dev/null | grep -q "$2" +} + +# --- START --- +do_start() { + echo "Starting CTF router challenge..." + + # CybICS muss laufen + if ! docker network ls --format '{{.Name}}' | grep -q "$INT_NET"; then + echo "ERROR: $INT_NET not found. Start CybICS first." + exit 1 + fi + + ATTACK=$(find_container "$ATTACK_CONTAINER") + [ -n "$ATTACK" ] && echo "Found attack machine: $ATTACK" + + # ext_ctf Netz anlegen + if ! docker network ls --format '{{.Name}}' | grep -q "^${EXT_NET}$"; then + docker network create --driver bridge --subnet "$EXT_SUBNET" --gateway "$EXT_GATEWAY" "$EXT_NET" \ + || { echo "ERROR: could not create $EXT_NET"; exit 1; } + fi + + # Router hochfahren + (cd "$ROUTER_DIR" && docker compose up -d --build) + sleep 3 + if ! docker ps --format '{{.Names}}' | grep -q "$ROUTER_CONTAINER"; then + echo "ERROR: router container not running" + exit 1 + fi + + # Router in beide Netze hängen + container_in_network "$ROUTER_CONTAINER" "$INT_NET" \ + || docker network connect --ip "$ROUTER_INT_IP" "$INT_NET" "$ROUTER_CONTAINER" + container_in_network "$ROUTER_CONTAINER" "$EXT_NET" \ + || docker network connect --ip "$ROUTER_EXT_IP" "$EXT_NET" "$ROUTER_CONTAINER" + + # Attack-Machine zusätzlich ins ext_ctf (bleibt im internen wegen Docker port-mapping Limitation) + if [ -n "$ATTACK" ]; then + container_in_network "$ATTACK" "$EXT_NET" \ + || docker network connect --ip "$ATTACK_EXT_IP" "$EXT_NET" "$ATTACK" + fi + + # Warten bis SSH antwortet + echo -n "Waiting for router SSH" + for _ in $(seq 1 24); do + nc -z -w2 127.0.0.1 2222 2>/dev/null && break + echo -n "." + sleep 5 + done + echo " ok" + + echo "" + echo "CTF router challenge running." + echo "" + echo "Router:" + echo " internal $ROUTER_INT_IP (virt-cybics)" + echo " external $ROUTER_EXT_IP (ext_ctf)" + echo " SSH localhost:2222 (root/password)" + echo "" + echo "From a Kali VM (real isolation):" + echo " nmap -> find port 2222" + echo " ssh root@ -p 2222" + echo " then pivot into 172.18.0.0/24" + echo "" + if [ -n "$ATTACK" ]; then + echo "Attack machine: $ATTACK_EXT_IP in ext_ctf" + echo " (stays in virt-cybics too — docker limitation)" + echo " noVNC still at localhost:6081" + fi +} + +# --- STOP --- +do_stop() { + echo "Stopping CTF router challenge..." + + ATTACK=$(find_container "$ATTACK_CONTAINER") + if [ -n "$ATTACK" ]; then + container_in_network "$ATTACK" "$EXT_NET" \ + && docker network disconnect "$EXT_NET" "$ATTACK" 2>/dev/null + fi + + if docker ps --format '{{.Names}}' | grep -q "$ROUTER_CONTAINER"; then + (cd "$ROUTER_DIR" && docker compose down --timeout 5) + fi + + docker network ls --format '{{.Name}}' | grep -q "^${EXT_NET}$" \ + && docker network rm "$EXT_NET" 2>/dev/null + + echo "Stopped. Back to normal." +} + +# --- STATUS --- +do_status() { + echo "CTF Router Challenge status:" + echo "" + + if docker ps --format '{{.Names}}' | grep -q "$ROUTER_CONTAINER"; then + echo " router: running" + container_in_network "$ROUTER_CONTAINER" "$INT_NET" && echo " -> $INT_NET ($ROUTER_INT_IP)" + container_in_network "$ROUTER_CONTAINER" "$EXT_NET" && echo " -> $EXT_NET ($ROUTER_EXT_IP)" + else + echo " router: not running" + fi + + if docker network ls --format '{{.Name}}' | grep -q "^${EXT_NET}$"; then + echo " ext_ctf: exists" + else + echo " ext_ctf: not created" + fi + + ATTACK=$(find_container "$ATTACK_CONTAINER") + if [ -n "$ATTACK" ]; then + if container_in_network "$ATTACK" "$EXT_NET"; then + echo " attack-vm: ctf mode (ext_ctf + virt-cybics)" + else + echo " attack-vm: normal (virt-cybics only)" + fi + else + echo " attack-vm: not found" + fi + echo "" +} + +case "${1:-}" in + start) do_start ;; + stop) do_stop ;; + status) do_status ;; + *) echo "Usage: $0 {start|stop|status}"; exit 1 ;; +esac \ No newline at end of file From a96687ccbcdfacdb8a74d4412eacc9f6f872824a Mon Sep 17 00:00:00 2001 From: franzifk Date: Mon, 13 Apr 2026 13:13:08 +0200 Subject: [PATCH 9/9] Merge branch '7-router-virtualsiert' of github.com:niklashaug/CybICS into 7-router-virtualsiert