From 2d98ca843f98351869a4c126520f97757913b871 Mon Sep 17 00:00:00 2001 From: alexz Date: Sun, 28 Dec 2025 22:56:51 +0000 Subject: [PATCH] rego-tunnel: parameterize net + add DHCP static lease --- apps/rego-tunnel/build/Dockerfile | 5 +- apps/rego-tunnel/build/setup-network.sh | 63 +++++++++++++--------- apps/rego-tunnel/build/start-dnsmasq.sh | 34 ++++++++++++ apps/rego-tunnel/build/start-vm.sh | 4 +- apps/rego-tunnel/build/supervisord.conf | 10 ++++ apps/rego-tunnel/config.json | 72 +++++++++++++++++++++++++ apps/rego-tunnel/docker-compose.yml | 10 ++++ 7 files changed, 169 insertions(+), 29 deletions(-) create mode 100644 apps/rego-tunnel/build/start-dnsmasq.sh diff --git a/apps/rego-tunnel/build/Dockerfile b/apps/rego-tunnel/build/Dockerfile index 6e21317..6953022 100755 --- a/apps/rego-tunnel/build/Dockerfile +++ b/apps/rego-tunnel/build/Dockerfile @@ -2,7 +2,7 @@ FROM ubuntu:24.04 ENV DEBIAN_FRONTEND=noninteractive -RUN apt-get update && apt-get install -y qemu-system-x86 qemu-utils novnc websockify openssh-server supervisor iproute2 bridge-utils iptables nano net-tools p7zip-full && rm -rf /var/lib/apt/lists/* +RUN apt-get update && apt-get install -y qemu-system-x86 qemu-utils novnc websockify openssh-server supervisor iproute2 bridge-utils iptables nano net-tools p7zip-full dnsmasq && rm -rf /var/lib/apt/lists/* # Setup SSH RUN mkdir /var/run/sshd && echo 'root:vmpassword' | chpasswd && sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config @@ -12,6 +12,7 @@ WORKDIR /vm COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf COPY start-vm.sh /usr/local/bin/start-vm.sh COPY setup-network.sh /usr/local/bin/setup-network.sh -RUN chmod +x /usr/local/bin/start-vm.sh /usr/local/bin/setup-network.sh +COPY start-dnsmasq.sh /usr/local/bin/start-dnsmasq.sh +RUN chmod +x /usr/local/bin/start-vm.sh /usr/local/bin/setup-network.sh /usr/local/bin/start-dnsmasq.sh CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"] diff --git a/apps/rego-tunnel/build/setup-network.sh b/apps/rego-tunnel/build/setup-network.sh index 5ac3466..63185e4 100755 --- a/apps/rego-tunnel/build/setup-network.sh +++ b/apps/rego-tunnel/build/setup-network.sh @@ -1,10 +1,21 @@ #!/bin/bash # Setup TAP/Bridge networking for QEMU VM -# Bridge: 100.100.0.1/24 -# VM will be: 100.100.0.2/24 +# Defaults: +# BRIDGE_NAME=br-rego-vpn +# TAP_NAME=tap0 +# BRIDGE_CIDR=100.100.0.1/24 +# VM_NET_IP=100.100.0.2 +# VM_SUBNET=100.100.0.0/24 set -e +BRIDGE_NAME="${BRIDGE_NAME:-br-rego-vpn}" +TAP_NAME="${TAP_NAME:-tap0}" +BRIDGE_CIDR="${BRIDGE_CIDR:-100.100.0.1/24}" +VM_NET_IP="${VM_NET_IP:-100.100.0.2}" +VM_SUBNET="${VM_SUBNET:-100.100.0.0/24}" +TARGET_IP="${TARGET_IP:-10.35.33.230}" + # Pick the outbound interface based on the container's default route. # (In Docker, this is not always eth1 when multiple networks are attached.) WAN_IF="$(ip route show default 0.0.0.0/0 2>/dev/null | awk '{for(i=1;i<=NF;i++) if($i=="dev"){print $(i+1); exit}}')" @@ -13,44 +24,44 @@ if [ -z "${WAN_IF}" ]; then fi # Create bridge if not exists -if ! ip link show br0 &>/dev/null; then - ip link add br0 type bridge - ip addr add 100.100.0.1/24 dev br0 - ip link set br0 up - echo "Bridge br0 created with IP 100.100.0.1/24" +if ! ip link show "$BRIDGE_NAME" &>/dev/null; then + ip link add "$BRIDGE_NAME" type bridge + ip addr add "$BRIDGE_CIDR" dev "$BRIDGE_NAME" + ip link set "$BRIDGE_NAME" up + echo "Bridge $BRIDGE_NAME created with IP $BRIDGE_CIDR" fi # Create TAP device if not exists -if ! ip link show tap0 &>/dev/null; then - ip tuntap add tap0 mode tap - ip link set tap0 master br0 - ip link set tap0 up - echo "TAP device tap0 created and attached to br0" +if ! ip link show "$TAP_NAME" &>/dev/null; then + ip tuntap add "$TAP_NAME" mode tap + ip link set "$TAP_NAME" master "$BRIDGE_NAME" + ip link set "$TAP_NAME" up + echo "TAP device $TAP_NAME created and attached to $BRIDGE_NAME" fi # Enable IP forwarding echo 1 > /proc/sys/net/ipv4/ip_forward # Setup NAT/masquerade for outbound traffic from VM -iptables -t nat -C POSTROUTING -s 100.100.0.0/24 -o "$WAN_IF" -j MASQUERADE 2>/dev/null || \ - iptables -t nat -A POSTROUTING -s 100.100.0.0/24 -o "$WAN_IF" -j MASQUERADE +iptables -t nat -C POSTROUTING -s "$VM_SUBNET" -o "$WAN_IF" -j MASQUERADE 2>/dev/null || \ + iptables -t nat -A POSTROUTING -s "$VM_SUBNET" -o "$WAN_IF" -j MASQUERADE # Ensure forwarding between the VM bridge and outbound interface -iptables -C FORWARD -i br0 -o "$WAN_IF" -j ACCEPT 2>/dev/null || \ - iptables -A FORWARD -i br0 -o "$WAN_IF" -j ACCEPT -iptables -C FORWARD -i "$WAN_IF" -o br0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT 2>/dev/null || \ - iptables -A FORWARD -i "$WAN_IF" -o br0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +iptables -C FORWARD -i "$BRIDGE_NAME" -o "$WAN_IF" -j ACCEPT 2>/dev/null || \ + iptables -A FORWARD -i "$BRIDGE_NAME" -o "$WAN_IF" -j ACCEPT +iptables -C FORWARD -i "$WAN_IF" -o "$BRIDGE_NAME" -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT 2>/dev/null || \ + iptables -A FORWARD -i "$WAN_IF" -o "$BRIDGE_NAME" -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -# Forward traffic destined for VPN networks to VM (10.35.33.230 = IBM i) +# Forward traffic destined for VPN networks to VM (TARGET_IP defaults to IBM i) # The VM will route this through its VPN tunnel -iptables -C FORWARD -d 10.35.33.230 -j ACCEPT 2>/dev/null || iptables -A FORWARD -d 10.35.33.230 -j ACCEPT -iptables -C FORWARD -s 10.35.33.230 -j ACCEPT 2>/dev/null || iptables -A FORWARD -s 10.35.33.230 -j ACCEPT +iptables -C FORWARD -d "$TARGET_IP" -j ACCEPT 2>/dev/null || iptables -A FORWARD -d "$TARGET_IP" -j ACCEPT +iptables -C FORWARD -s "$TARGET_IP" -j ACCEPT 2>/dev/null || iptables -A FORWARD -s "$TARGET_IP" -j ACCEPT -# Route to IBM i through VM -ip route add 10.35.33.230 via 100.100.0.2 2>/dev/null || true +# Route to TARGET_IP through VM +ip route add "$TARGET_IP" via "$VM_NET_IP" 2>/dev/null || true echo "Network setup complete" -echo "Bridge: br0 = 100.100.0.1/24" -echo "TAP: tap0 attached to br0" -echo "Route: 10.35.33.230 via 100.100.0.2 (VM)" +echo "Bridge: $BRIDGE_NAME = $BRIDGE_CIDR" +echo "TAP: $TAP_NAME attached to $BRIDGE_NAME" +echo "Route: $TARGET_IP via $VM_NET_IP (VM)" echo "Outbound interface: ${WAN_IF}" diff --git a/apps/rego-tunnel/build/start-dnsmasq.sh b/apps/rego-tunnel/build/start-dnsmasq.sh new file mode 100644 index 0000000..9227fd8 --- /dev/null +++ b/apps/rego-tunnel/build/start-dnsmasq.sh @@ -0,0 +1,34 @@ +#!/bin/bash +set -euo pipefail + +BRIDGE_NAME="${BRIDGE_NAME:-br-rego-vpn}" +BRIDGE_CIDR="${BRIDGE_CIDR:-100.100.0.1/24}" +VM_NET_IP="${VM_NET_IP:-100.100.0.2}" +VM_MAC="${VM_MAC:-52:54:00:12:34:56}" + +LEASE_TIME="${LEASE_TIME:-12h}" +DNS_SERVERS="${DNS_SERVERS:-1.1.1.1,8.8.8.8}" + +GATEWAY_IP="${BRIDGE_CIDR%%/*}" + +mkdir -p /etc/dnsmasq.d + +cat > /etc/dnsmasq.d/rego.conf < ${VM_NET_IP}" +exec dnsmasq --no-daemon --conf-file=/etc/dnsmasq.d/rego.conf diff --git a/apps/rego-tunnel/build/start-vm.sh b/apps/rego-tunnel/build/start-vm.sh index 28b175b..c3a87ec 100755 --- a/apps/rego-tunnel/build/start-vm.sh +++ b/apps/rego-tunnel/build/start-vm.sh @@ -23,6 +23,8 @@ fi # Wait for network setup sleep 2 +TAP_NAME="${TAP_NAME:-tap0}" + exec qemu-system-x86_64 \ -enable-kvm \ -cpu host \ @@ -31,7 +33,7 @@ exec qemu-system-x86_64 \ -hda /vm/linux-vm.qcow2 \ -fsdev local,id=fsdev0,path=/shared,security_model=none,multidevs=remap \ -device virtio-9p-pci,fsdev=fsdev0,mount_tag=shared \ - -netdev tap,id=net0,ifname=tap0,script=no,downscript=no \ + -netdev tap,id=net0,ifname="$TAP_NAME",script=no,downscript=no \ -device virtio-net-pci,netdev=net0,mac=52:54:00:12:34:56 \ -vnc :0 \ -vga virtio \ diff --git a/apps/rego-tunnel/build/supervisord.conf b/apps/rego-tunnel/build/supervisord.conf index 3e0d82e..1c3b949 100755 --- a/apps/rego-tunnel/build/supervisord.conf +++ b/apps/rego-tunnel/build/supervisord.conf @@ -13,6 +13,16 @@ stdout_logfile_maxbytes=0 stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0 +[program:dnsmasq] +command=/usr/local/bin/start-dnsmasq.sh +autostart=true +autorestart=true +priority=5 +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 + [program:sshd] command=/usr/sbin/sshd -D autostart=true diff --git a/apps/rego-tunnel/config.json b/apps/rego-tunnel/config.json index 37793f6..2b83609 100755 --- a/apps/rego-tunnel/config.json +++ b/apps/rego-tunnel/config.json @@ -28,6 +28,78 @@ "placeholder": "4", "required": true, "env_variable": "WINDOWS_CPU_CORES" + }, + { + "type": "text", + "label": "VM IP (internal)", + "hint": "Internal VM IP on the tap/bridge network", + "placeholder": "100.100.0.2", + "required": true, + "env_variable": "VM_NET_IP" + }, + { + "type": "text", + "label": "VM MAC", + "hint": "Used for DHCP reservation (VM must use DHCP)", + "placeholder": "52:54:00:12:34:56", + "required": true, + "env_variable": "VM_MAC" + }, + { + "type": "text", + "label": "Bridge name", + "hint": "Linux bridge created inside the container for VM networking", + "placeholder": "br-rego-vpn", + "required": true, + "env_variable": "BRIDGE_NAME" + }, + { + "type": "text", + "label": "TAP name", + "hint": "Tap interface name used by QEMU", + "placeholder": "tap0", + "required": true, + "env_variable": "TAP_NAME" + }, + { + "type": "text", + "label": "Bridge CIDR", + "hint": "Bridge address/CIDR assigned inside the container", + "placeholder": "100.100.0.1/24", + "required": true, + "env_variable": "BRIDGE_CIDR" + }, + { + "type": "text", + "label": "VM subnet", + "hint": "Subnet that should be NATed out of the container", + "placeholder": "100.100.0.0/24", + "required": true, + "env_variable": "VM_SUBNET" + }, + { + "type": "text", + "label": "Target IP (routed via VM)", + "hint": "Traffic to this IP is routed via the VM (VPN inside the VM)", + "placeholder": "10.35.33.230", + "required": true, + "env_variable": "TARGET_IP" + }, + { + "type": "text", + "label": "DNS servers", + "hint": "DNS servers offered to the VM via DHCP", + "placeholder": "1.1.1.1,8.8.8.8", + "required": true, + "env_variable": "DNS_SERVERS" + }, + { + "type": "text", + "label": "DHCP lease time", + "hint": "Lease duration (dnsmasq format, e.g. 12h)", + "placeholder": "12h", + "required": true, + "env_variable": "LEASE_TIME" } ], "supported_architectures": ["amd64"] diff --git a/apps/rego-tunnel/docker-compose.yml b/apps/rego-tunnel/docker-compose.yml index 37fb96d..e0b8c5c 100755 --- a/apps/rego-tunnel/docker-compose.yml +++ b/apps/rego-tunnel/docker-compose.yml @@ -15,9 +15,19 @@ services: environment: - VM_RAM=${WINDOWS_RAM_GB}G - VM_CPUS=${WINDOWS_CPU_CORES} + - BRIDGE_NAME=${BRIDGE_NAME:-br-rego-vpn} + - TAP_NAME=${TAP_NAME:-tap0} + - BRIDGE_CIDR=${BRIDGE_CIDR:-100.100.0.1/24} + - VM_NET_IP=${VM_NET_IP:-100.100.0.2} + - VM_SUBNET=${VM_SUBNET:-100.100.0.0/24} + - TARGET_IP=${TARGET_IP:-10.35.33.230} + - VM_MAC=${VM_MAC:-52:54:00:12:34:56} + - DNS_SERVERS=${DNS_SERVERS:-1.1.1.1,8.8.8.8} + - LEASE_TIME=${LEASE_TIME:-12h} volumes: - /etc/runtipi/user-config/runtipi/rego-tunnel/storage/linux-vm.qcow2:/vm/linux-vm.qcow2 - /etc/runtipi/user-config/runtipi/rego-tunnel/shared:/shared + - /etc/runtipi/app-data:/shared/app-data networks: - tipi_main_network sysctls: