Created
April 9, 2023 13:25
-
-
Save NerdyProjects/059759af292887b93690fee852a36bf0 to your computer and use it in GitHub Desktop.
OpenWRT VPN policy routing setup script
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
# VPN policy routing setup generator for OpenWRT 22 & 23 (Snapshot as of 2023-04-09) | |
# Creates network devices / bridge for "WAN" and "LAN" and sets up policy routing so traffic from "LAN" only exits via VPN. | |
# Can be used simultaneously for multiple VPNs as long as their IP space is separate. | |
# Based on https://kiljan.org/2020/03/27/vpn-as-wan-for-guest-network-on-openwrt/ | |
# interface name for lan interface (e.g. what clients will connect to). | |
# also used for bridge interface and firewall ruleset as well as routing table | |
LAN_IFNAME=guest | |
# IP address of this router on the lan interface. Will have DHCP enabled. | |
LAN_IP=192.168.42.1 | |
# routing table ID | |
ROUTE_TABLE_ID=42 | |
# interface name for wan interface to be created and linked to the OpenVPN instance | |
WAN_VPN_IFNAME=wan_pvpn | |
# OpenVPN tun interface name. Use explicit numbering also in OpenVPN config. | |
TUN=tun1 | |
# Optionally, add route up/down scripts to OpenVPN config. | |
# alternatively, do the changes from the following lines manually: | |
#OVPN_CONF=/etc/openvpn/projekt.ovpn | |
# | |
# | |
#cat << EOI >> $OVPN_CONF | |
#route-noexec | |
#script-security 2 | |
#route-up /etc/openvpn/routes-$LAN_IFNAME.sh | |
#route-pre-down /etc/openvpn/routes-$LAN_IFNAME.sh | |
#EOI | |
grep ^$ROUTE_TABLE_ID /etc/iproute2/rt_tables | |
if [ 0 -eq "$?" ]; then | |
echo routing table ID $ROUTE_TABLE_ID already exists, aborting | |
exit 1 | |
fi | |
cat << EOF >> /etc/iproute2/rt_tables | |
$ROUTE_TABLE_ID $LAN_IFNAME | |
EOF | |
uci batch << EOI | |
set dhcp.$LAN_IFNAME=dhcp | |
set dhcp.$LAN_IFNAME.interface='$LAN_IFNAME' | |
set dhcp.$LAN_IFNAME.start='100' | |
set dhcp.$LAN_IFNAME.limit='150' | |
set dhcp.$LAN_IFNAME.leasetime='12h' | |
set dhcp.$LAN_IFNAME.dhcp_option='6,9.9.9.9,149.112.112.112' | |
EOI | |
DEVICE=$(uci add network device) | |
uci batch << EOI | |
set network.$DEVICE.type='bridge' | |
set network.$DEVICE.name='br-$LAN_IFNAME' | |
set network.$DEVICE.bridge_empty='1' | |
set network.$LAN_IFNAME=interface | |
set network.$LAN_IFNAME.proto='static' | |
set network.$LAN_IFNAME.device='br-$LAN_IFNAME' | |
set network.$LAN_IFNAME.ipaddr='$LAN_IP' | |
set network.$LAN_IFNAME.netmask='255.255.255.0' | |
set network.$LAN_IFNAME.delegate='0' | |
set network.$WAN_VPN_IFNAME=interface | |
set network.$WAN_VPN_IFNAME.proto='none' | |
set network.$WAN_VPN_IFNAME.device='$TUN' | |
EOI | |
RULE=$(uci add firewall rule) | |
uci batch << EOI | |
set firewall.$RULE.name='Allow $LAN_IFNAME dhcp' | |
set firewall.$RULE.proto='udp' | |
set firewall.$RULE.src='$LAN_IFNAME' | |
set firewall.$RULE.src_port='68' | |
set firewall.$RULE.dest_port='67' | |
set firewall.$RULE.target='ACCEPT' | |
set firewall.$RULE.family='ipv4' | |
EOI | |
ZONE_WAN_VPN=$(uci add firewall zone) | |
ZONE_LAN=$(uci add firewall zone) | |
FORWARDING=$(uci add firewall forwarding) | |
uci batch << EOI | |
set firewall.$ZONE_WAN_VPN.name='$WAN_VPN_IFNAME' | |
set firewall.$ZONE_WAN_VPN.input='REJECT' | |
set firewall.$ZONE_WAN_VPN.output='ACCEPT' | |
set firewall.$ZONE_WAN_VPN.forward='REJECT' | |
set firewall.$ZONE_WAN_VPN.masq='1' | |
set firewall.$ZONE_WAN_VPN.mtu_fix='1' | |
set firewall.$ZONE_WAN_VPN.network='$WAN_VPN_IFNAME' | |
set firewall.$ZONE_LAN.name='$LAN_IFNAME' | |
set firewall.$ZONE_LAN.input='REJECT' | |
set firewall.$ZONE_LAN.output='ACCEPT' | |
set firewall.$ZONE_LAN.forward='REJECT' | |
set firewall.$ZONE_LAN.network='$LAN_IFNAME' | |
set firewall.$FORWARDING.src='$LAN_IFNAME' | |
set firewall.$FORWARDING.dest='$WAN_VPN_IFNAME' | |
EOI | |
cat << EOF > /etc/openvpn/routes-$LAN_IFNAME.sh | |
#!/usr/bin/env sh | |
table=$LAN_IFNAME | |
if [ "\$script_type" == "route-up" ]; then | |
ip route add default via \$route_vpn_gateway dev \$dev table \$table proto static | |
elif [ "\$script_type" == "route-pre-down" ]; then | |
ip route del default via \$route_vpn_gateway dev \$dev table \$table proto static | |
fi | |
EOF | |
chmod +x /etc/openvpn/routes-$LAN_IFNAME.sh | |
cat << EOF >> /etc/sysupgrade.conf | |
/etc/hotplug.d/iface/99-$LAN_IFNAME | |
EOF | |
cat << EOF > /etc/hotplug.d/iface/99-$LAN_IFNAME | |
#!/usr/bin/env sh | |
if=$LAN_IFNAME | |
dev=\$DEVICE | |
table=\$INTERFACE | |
if2dev() { | |
dev=\$(uci get network.\$1.ifname) | |
[ \$(echo \$dev | wc -w) -gt 1 ] && dev=br-\$1 | |
echo \$dev | |
} | |
if [ "\$INTERFACE" == "\$if" ]; then | |
if [ "\$ACTION" == "ifup" ]; then | |
ip rule add iif \$dev lookup \$table | |
elif [ "\$ACTION" == "ifdown" ]; then | |
# Workaround for missing \$DEVICE when interface is going down | |
dev=\$(if2dev \$if) | |
ip rule del iif \$dev lookup \$table | |
fi | |
fi | |
EOF | |
echo "Done. Please check and run uci commit, afterwards restart interfaces or router." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment