From 3b6eb65dc5c95f6ca4a0e3672b099cad7aa4730e Mon Sep 17 00:00:00 2001 From: Parahub AI Date: Thu, 5 Feb 2026 15:26:21 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20guest=20traffic=20via=20GRE6=E2=86=92VP?= =?UTF-8?q?S=E2=86=92Mullvad,=20OWE,=20DNS=20security,=20SSH=20key?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - GRE6 tunnel over Yggdrasil to VPS gateway (172.16.0.0/24) - Kill switch: guest→vpn_tunnel only (no guest→wan) - OWE transition mode on Parahub_Free (encrypted + open fallback) - DNS-over-HTTPS via https-dns-proxy (Cloudflare 1.1.1.1) - Guest DNS hijacked via firewall DNAT redirect - IPv6 blocked for guest zone (leak prevention) - SQM 128→512 kbps - Added kmod-gre6, https-dns-proxy to PACKAGES_CORE - SSH authorized key for passwordless root access Co-Authored-By: Claude Opus 4.5 --- files/etc/dropbear/authorized_keys | 1 + files/etc/uci-defaults/99-parahub-mesh | 101 ++++++++++++++++++++++--- scripts/build.sh | 8 +- 3 files changed, 97 insertions(+), 13 deletions(-) create mode 100644 files/etc/dropbear/authorized_keys diff --git a/files/etc/dropbear/authorized_keys b/files/etc/dropbear/authorized_keys new file mode 100644 index 0000000..cf83b5e --- /dev/null +++ b/files/etc/dropbear/authorized_keys @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILcethx5tVJWXTj4GjG7h75Fr3IKrwdkpBRc8sN6uRrA andrey.perliev@gmail.com diff --git a/files/etc/uci-defaults/99-parahub-mesh b/files/etc/uci-defaults/99-parahub-mesh index 90f85ec..e8db098 100755 --- a/files/etc/uci-defaults/99-parahub-mesh +++ b/files/etc/uci-defaults/99-parahub-mesh @@ -123,6 +123,15 @@ set network.guest.netmask='255.255.255.0' set network.wan=interface set network.wan.device='eth1' set network.wan.proto='dhcp' + +# --- GRE6 tunnel (guest traffic → VPS gateway via Yggdrasil) --- +set network.vpn_tunnel=interface +set network.vpn_tunnel.proto='grev6' +set network.vpn_tunnel.peeraddr='200:39f1:6a26:328a:d901:fbd2:d30d:faef' +set network.vpn_tunnel.ipaddr='172.16.0.2' +set network.vpn_tunnel.netmask='255.255.255.0' +set network.vpn_tunnel.gateway='172.16.0.1' +set network.vpn_tunnel.mtu='1400' NET_EOF uci commit network @@ -186,13 +195,15 @@ set wireless.mesh_2g.key='${MESH_KEY}' set wireless.mesh_2g.network='bat0_hardif_mesh0' WIFI_2G_MESH - # Public AP on 2.4GHz (better range) + # Public AP on 2.4GHz (better range) — OWE transition mode + # Devices that support OWE get encrypted; legacy devices fall back to open uci batch <<-WIFI_2G_PUB set wireless.public_2g=wifi-iface set wireless.public_2g.device='${RADIO_2G}' set wireless.public_2g.mode='ap' set wireless.public_2g.ssid='${PUBLIC_SSID}' -set wireless.public_2g.encryption='none' +set wireless.public_2g.encryption='owe' +set wireless.public_2g.owe_transition='1' set wireless.public_2g.isolate='1' set wireless.public_2g.network='guest' WIFI_2G_PUB @@ -234,6 +245,7 @@ uci commit wireless while uci -q delete firewall.@zone[0]; do :; done while uci -q delete firewall.@forwarding[0]; do :; done while uci -q delete firewall.@rule[0]; do :; done +while uci -q delete firewall.@redirect[0]; do :; done uci batch <<-FW_EOF # --- Zone: lan (private network) --- @@ -244,12 +256,13 @@ set firewall.@zone[-1].output='ACCEPT' set firewall.@zone[-1].forward='ACCEPT' add_list firewall.@zone[-1].network='private' -# --- Zone: guest --- +# --- Zone: guest (IPv4 only — IPv6 blocked) --- add firewall zone set firewall.@zone[-1].name='guest' set firewall.@zone[-1].input='REJECT' set firewall.@zone[-1].output='ACCEPT' set firewall.@zone[-1].forward='REJECT' +set firewall.@zone[-1].family='ipv4' add_list firewall.@zone[-1].network='guest' # --- Zone: wan --- @@ -262,15 +275,25 @@ set firewall.@zone[-1].masq='1' set firewall.@zone[-1].mtu_fix='1' add_list firewall.@zone[-1].network='wan' +# --- Zone: vpn_tunnel (GRE6 → VPS → Mullvad) --- +add firewall zone +set firewall.@zone[-1].name='vpn_tunnel' +set firewall.@zone[-1].input='REJECT' +set firewall.@zone[-1].output='ACCEPT' +set firewall.@zone[-1].forward='REJECT' +set firewall.@zone[-1].masq='1' +set firewall.@zone[-1].mtu_fix='1' +add_list firewall.@zone[-1].network='vpn_tunnel' + # --- Forwarding: lan → wan (internet for owner) --- add firewall forwarding set firewall.@forwarding[-1].src='lan' set firewall.@forwarding[-1].dest='wan' -# --- Forwarding: guest → wan (internet for guests) --- +# --- Forwarding: guest → vpn_tunnel ONLY (kill switch: no wan!) --- add firewall forwarding set firewall.@forwarding[-1].src='guest' -set firewall.@forwarding[-1].dest='wan' +set firewall.@forwarding[-1].dest='vpn_tunnel' # --- Rule: guest DHCP (allow guests to get IP) --- add firewall rule @@ -279,14 +302,16 @@ set firewall.@rule[-1].src='guest' set firewall.@rule[-1].proto='udp' set firewall.@rule[-1].dest_port='67' set firewall.@rule[-1].target='ACCEPT' +set firewall.@rule[-1].family='ipv4' -# --- Rule: guest DNS (allow guests to resolve) --- +# --- Rule: guest DNS to router only (hijacked to DoH) --- add firewall rule set firewall.@rule[-1].name='Guest DNS' set firewall.@rule[-1].src='guest' set firewall.@rule[-1].proto='tcpudp' set firewall.@rule[-1].dest_port='53' set firewall.@rule[-1].target='ACCEPT' +set firewall.@rule[-1].family='ipv4' # --- Rule: block guest → lan (isolation) --- add firewall rule @@ -296,6 +321,25 @@ set firewall.@rule[-1].dest='lan' set firewall.@rule[-1].proto='all' set firewall.@rule[-1].target='REJECT' +# --- Rule: block ALL IPv6 from guest (leak prevention) --- +add firewall rule +set firewall.@rule[-1].name='Block guest IPv6' +set firewall.@rule[-1].src='guest' +set firewall.@rule[-1].proto='all' +set firewall.@rule[-1].family='ipv6' +set firewall.@rule[-1].target='REJECT' + +# --- DNS hijack: redirect guest DNS to local DoH resolver --- +add firewall redirect +set firewall.@redirect[-1].name='Guest DNS hijack' +set firewall.@redirect[-1].src='guest' +set firewall.@redirect[-1].src_dport='53' +set firewall.@redirect[-1].proto='tcpudp' +set firewall.@redirect[-1].target='DNAT' +set firewall.@redirect[-1].dest='lan' +set firewall.@redirect[-1].dest_port='53' +set firewall.@redirect[-1].family='ipv4' + # --- Standard WAN input rules --- add firewall rule set firewall.@rule[-1].name='Allow-DHCP-Renew' @@ -340,7 +384,7 @@ DHCP_EOF uci commit dhcp # ============================================================================ -# 8. SQM TRAFFIC SHAPING (guest 128 kbps limit) +# 8. SQM TRAFFIC SHAPING (guest 512 kbps limit) # ============================================================================ # Find the guest interface device name (will be set after network restart) @@ -350,8 +394,8 @@ uci batch <<-SQM_EOF set sqm.guest=queue set sqm.guest.enabled='1' set sqm.guest.interface='br-guest' -set sqm.guest.download='128' -set sqm.guest.upload='128' +set sqm.guest.download='512' +set sqm.guest.upload='512' set sqm.guest.qdisc='cake' set sqm.guest.script='piece_of_cake.qos' set sqm.guest.linklayer='ethernet' @@ -360,7 +404,35 @@ SQM_EOF uci commit sqm # ============================================================================ -# 9. SYSTEM SETTINGS +# 9. DNS-OVER-HTTPS (guest DNS privacy) +# ============================================================================ + +# https-dns-proxy: local DoH resolver for guest DNS queries +# Guest DNS is hijacked via firewall redirect to this resolver +uci batch <<-DOH_EOF +set https-dns-proxy.main=main +set https-dns-proxy.main.doh_paramters='-4' +set https-dns-proxy.main.listen_addr='0.0.0.0' +set https-dns-proxy.main.listen_port='5053' + +set https-dns-proxy.cloudflare=https-dns-proxy +set https-dns-proxy.cloudflare.resolver_url='https://1.1.1.1/dns-query' +set https-dns-proxy.cloudflare.listen_addr='127.0.0.1' +set https-dns-proxy.cloudflare.listen_port='5053' +DOH_EOF +uci commit https-dns-proxy + +# Configure dnsmasq to use DoH for upstream +uci -q delete dhcp.@dnsmasq[0].server 2>/dev/null || true +uci add_list dhcp.@dnsmasq[0].server='127.0.0.1#5053' +uci set dhcp.@dnsmasq[0].noresolv='1' +uci commit dhcp + +# Enable https-dns-proxy service +/etc/init.d/https-dns-proxy enable 2>/dev/null || true + +# ============================================================================ +# 10. SYSTEM SETTINGS # ============================================================================ uci batch <<-SYS_EOF @@ -374,12 +446,15 @@ SYS_EOF uci commit system # ============================================================================ -# 10. YGGDRASIL OVERLAY NETWORK +# 11. YGGDRASIL OVERLAY NETWORK # ============================================================================ # Generate unique keys for this node yggdrasil -genconf | sed 's/IfName: .*/IfName: ygg0/' > /etc/yggdrasil.conf +# Add VPS gateway as static Yggdrasil peer (for GRE6 tunnel) +sed -i 's|Peers: \[\]|Peers: ["tls://91.98.123.238:443"]|' /etc/yggdrasil.conf + # UCI network interface for yggdrasil TUN uci batch <<-YGG_EOF set network.yggdrasil=interface @@ -400,7 +475,7 @@ YGG_ADDR=$(yggdrasil -address -useconffile /etc/yggdrasil.conf 2>/dev/null || ec echo "YGGDRASIL_ADDRESS=${YGG_ADDR}" >> /etc/parahub/keys # ============================================================================ -# 11. FINAL +# 12. FINAL # ============================================================================ # Log completion @@ -410,5 +485,7 @@ logger -t parahub-mesh "Private: ${PRIVATE_SSID} @ ${PRIV_IP}/24" logger -t parahub-mesh "Guest: ${PUBLIC_SSID} @ ${GUEST_IP}/24" logger -t parahub-mesh "Mesh ID: ${MESH_ID}" logger -t parahub-mesh "Yggdrasil: ${YGG_ADDR}" +logger -t parahub-mesh "GRE tunnel: 172.16.0.2 → VPS gateway (Mullvad Portugal)" +logger -t parahub-mesh "Kill switch: guest→vpn_tunnel only (no wan)" exit 0 diff --git a/scripts/build.sh b/scripts/build.sh index 92a72d7..1f92d02 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -54,13 +54,19 @@ PACKAGES_CORE=( kmod-batman-adv batctl-full - # 802.11s mesh support (replace basic wpad) + # 802.11s mesh support (replace basic wpad, includes OWE) wpad-mesh-mbedtls -wpad-basic-mbedtls # Yggdrasil overlay network yggdrasil + # GRE6 tunnel (guest traffic → VPS gateway) + kmod-gre6 + + # DNS-over-HTTPS for guest privacy + https-dns-proxy + # SQM traffic shaping sqm-scripts kmod-sched-cake