What's new
  • SNBForums Code of Conduct

    SNBForums is a community for everyone, no matter what their level of experience.

    Please be tolerant and patient of others, especially newcomers. We are all here to share and learn!

    The rules are simple: Be patient, be nice, be helpful or be gone!

Blocking internet traffic when VPN client connection fails

tom555

New Around Here
Hello everybody, i'm trying to find out how to block all internet traffic which is not goingthrough the openvpn client on vpn connection faillure. Using RT AC68U and 3.0.0.4.374.41_0 merlin firmware

I've tried doing this the way I used to with dd-wrt following https://airvpn.org/index.php?option=com_kunena&func=view&catid=3&id=4287&Itemid=142#4287 so I create a firewall-start file in the jffs/scripts directory with some iptables rules, but unfortunately it has no effect : when the vpn connection drops traffic goes through the regular internet connection (wan). here is the script I use:

#!/bin/sh
touch /tmp/000firewallstarted
iptables -I FORWARD -i br0 -o tap0 -j ACCEPT
iptables -I FORWARD -i tap0 -o br0 -j ACCEPT
iptables -I FORWARD -i br0 -o vlan1 -j DROP
iptables -I INPUT -i tap0 -j REJECT
iptables -t nat -A POSTROUTING -o tap0 -j MASQUERADE

I suspect it could be related with the interface I used which might be not correct :

br0 is supposed to be the bridge with the lan
vlan1 is supposed to be the wan connected to the ISP
tap0 is supposed to be the VPN interface

I use the openvpn client1 with tap interface so I tried the same script replacing tap0 with tap11 but it does not work either.

Any idea?

Thank you in advance
 
Last edited:
Hello everybody, i'm trying to find out how to block all internet traffic which is not goingthrough the openvpn client on vpn connection faillure. Using RT AC68U and 3.0.0.4.374.41_0 merlin firmware

I've tried doing this the way I used to with dd-wrt following https://airvpn.org/index.php?option=com_kunena&func=view&catid=3&id=4287&Itemid=142#4287 so I create a firewall-start file in the jffs/scripts directory with some iptables rules, but unfortunately it has no effect : when the vpn connection drops traffic goes through the regular internet connection (wan). here is the script I use:

#!/bin/sh
touch /tmp/000firewallstarted
iptables -I FORWARD -i br0 -o tap0 -j ACCEPT
iptables -I FORWARD -i tap0 -o br0 -j ACCEPT
iptables -I FORWARD -i br0 -o vlan1 -j DROP
iptables -I INPUT -i tap0 -j REJECT
iptables -t nat -A POSTROUTING -o tap0 -j MASQUERADE

I suspect it could be related with the interface I used which might be not correct :

br0 is supposed to be the bridge with the lan
vlan1 is supposed to be the wan connected to the ISP
tap0 is supposed to be the VPN interface

I use the openvpn client1 with tap interface so I tried the same script replacing tap0 with tap11 but it does not work either.

Any idea?

Thank you in advance

I use selective VPN routing and I use the following logic in my script...

Code:
# Optionally FORCE the use of the VPN tunnel, so if the VPN tunnel drops, the device will not use the unencrypted default WAN
if [ "$FORCE" = "FORCE" ];then
   logger -t "($(basename $0))" $$ VPN Selective routing for $IP_RANGE WAN access blocked
   echo "$IP_RANGE WAN access blocked"
   # Prevent duplicate blocking rule entries
   iptables -D FORWARD -i br0 -s $IP_RANGE -o eth0 -j DROP
   [COLOR="Red"]iptables -I FORWARD -i br0 -s $IP_RANGE -o eth0 -j DROP[/COLOR]
fi
# Allow removing of the WAN blocking if it was previously set
if [ "$FORCE" = "NOFORCE" ];then
   logger -t "($(basename $0))" $$ VPN Selective routing for $IP_RANGE WAN access allowed
   echo "$IP_RANGE WAN access allowed"
   [COLOR="Red"]iptables -D FORWARD -i br0 -s $IP_RANGE -o eth0 -j DROP[/COLOR]
fi

So not sure if specifying eth0 will work in your case?

Regards,
 
I use selective VPN routing and I use the following logic in my script...

Code:
# Optionally FORCE the use of the VPN tunnel, so if the VPN tunnel drops, the device will not use the unencrypted default WAN
if [ "$FORCE" = "FORCE" ];then
   logger -t "($(basename $0))" $$ VPN Selective routing for $IP_RANGE WAN access blocked
   echo "$IP_RANGE WAN access blocked"
   # Prevent duplicate blocking rule entries
   iptables -D FORWARD -i br0 -s $IP_RANGE -o eth0 -j DROP
   [COLOR="Red"]iptables -I FORWARD -i br0 -s $IP_RANGE -o eth0 -j DROP[/COLOR]
fi
# Allow removing of the WAN blocking if it was previously set
if [ "$FORCE" = "NOFORCE" ];then
   logger -t "($(basename $0))" $$ VPN Selective routing for $IP_RANGE WAN access allowed
   echo "$IP_RANGE WAN access allowed"
   [COLOR="Red"]iptables -D FORWARD -i br0 -s $IP_RANGE -o eth0 -j DROP[/COLOR]
fi

So not sure if specifying eth0 will work in your case?

Regards,

Yes! eth0 of instead vlan1 works perfectly, in fact my firewall-start script is now simply :

#!/bin/sh
touch /tmp/000firewallstarted
iptables -I FORWARD -i br0 -o eth0 -j DROP

Thanks a lot!

By the way I find your script interesting because of the iprange feature, could you post the whole script ? Is that your firewall-start file or do you put this elsewhere ?

TIA
 
Yes! eth0 of instead vlan1 works perfectly, in fact my firewall-start script is now simply :

#!/bin/sh
touch /tmp/000firewallstarted
iptables -I FORWARD -i br0 -o eth0 -j DROP

Thanks a lot!

By the way I find your script interesting because of the iprange feature, could you post the whole script ? Is that your firewall-start file or do you put this elsewhere ?

TIA

My crude script may be overkill for your requirements i.e. if you simply want to ensure that ALL traffic is always via the VPN then simply use:

Code:
iptables -I FORWARD -i br0 -s xxx.xxx.xxx.xxx -o eth0 -j DROP

where xxx.xxx.xxx.xxx is an appropriate subnet mask definition for your LAN.

Anyway here it is....

This a custom script that can be called at any time, but is actually always called from my custom OpenVPN client 'UP' script.
(I like to avoid having inline code in the recognised scripts such as wan-start, firewall-start etc.)

Code:
#!/bin/sh

# Usage:  VPN_select_ON_OFF [host.dnsmasq | ip_address | KEY_tag] {ON | OFF} {FORCE | NOFORCE}
#
#
#             where  Host.dnsmasq     will be matched against /etc/hosts.dnsmasq contents
#                    Key_tag          will be matched against /mnt/$MYROUTER/VPN_MASKS.txt
#
#                    ON | OFF         VPN routing (if omitted then the audit file will be used to flip)
#
#                    FORCE | NOFORCE  Enforce or remove WAN blocking

# e.g. For a specific device (Laptop)

#
#        VPN_select_ON_OFF   u200-115   on   force
#        VPN_select_ON_OFF   u200-115   off  noforce
#        VPN_select_ON_OFF   u200-115   off  

# e.g. IP Range

#        VPN_select_ON_OFF   192.168.10.8/29
#        VPN_select_ON_OFF   192.168.10.200-192.168.10.203   on   force

#        VPN_select_ON_OFF   192.168.10.8/29   force
#        VPN_select_ON_OFF   192.168.10.8/29   noforce
#

# e.g. A logical group of devices

#        VPN_select_ON_OFF   ANDROID  on

MYROUTER=$(nvram get computer_name)
USEPATH="/tmp/mnt/$MYROUTER"

logger -t "($(basename $0))" $$ VPN Selective routing for [$@]

# Translate input args into UPPERCASE
ACTION=`echo $2 | tr '[a-z]' '[A-Z]'`
FORCE=`echo $3 | tr '[a-z]' '[A-Z]'`

# Check if WAN access id to be blocked $2=FORCE requested
if [ "$ACTION" = "FORCE" ];then

   ACTION="NULL"
   FORCE="FORCE"
fi
# Check if WAN access id to be unblocked $2=NOFORCE requested
if [ "$ACTION" = "NOFORCE" ];then

   ACTION="NULL"
   FORCE="NOFORCE"
fi

# Perform a lookup if a hostname (or I/P address) is supplied
# NOTE: etc/host.dnsmasq is in format
#
#       I/P address    hostname
#
if [ "$1" != "" ];then
   IP_NAME=`echo $1 | tr '[a-z]' '[A-Z]'`
   IP_RANGE=`grep -i "$IP_NAME" /etc/hosts.dnsmasq  | awk '{print $1}'`
   logger -t "($(basename $0))" $$ "Lookup '$IP_NAME' in DNSMASQ returned:>$IP_RANGE<"

   # If entry not matched in /etc/hosts.dnsmasq see if it exists in our VPN_MASKS.txt lookup file
   #
   #       KEY     I/P address
   #
   if [ "$IP_RANGE" = "" ];then

      IP_RANGE=`grep -i "^$1" $USEPATH/VPN_MASKS.txt | awk '{print $2}'`
      logger -t "($(basename $0))" $$ "Lookup '$IP_NAME' in $USEPATH/VPN_MASKS.txt returned:>$IP_RANGE<"
   fi



else
   IP_NAME="U200-115"
   IP_RANGE=`grep -i $IP_NAME /etc/hosts.dnsmasq  | awk '{print $1}'`
   logger -t "($(basename $0))" $$ "DEFAULT '$IP_NAME' lookup returned:>$IP_RANGE<"
fi

echo "Processing options: $IP_NAME - $ACTION - $FORCE"

# Validate the I/P address
REGEX="\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b"

CHECK=$(echo $IP_RANGE | egrep $REGEX)
if [[ "$?" -eq 0 ]];then
   echo "Valid IP address " $IP_RANGE
else
   logger -t "($(basename $0))" $$ **ERROR Invalid IP address $IP_RANGE
   echo "Invalid IP address " $IP_RANGE
   exit 1
fi

if [ "$IP_RANGE" = "" ];then
   logger -t "($(basename $0))" $$ "**ERROR Missing arg: DNSMASQ hostname or IP address"
   echo "Missing arg: Hostname or IP address"
   exit 1
fi



# Flip the VPN selective routing if the tracking file exists and no explicit directive supplied
if [ -e $USEPATH/VPN_$IP_RANGE.txt ] && [ "$ACTION" = "" ] ;then

   # Retrieve the previous known status (Reboot should definitely delete these files?  - see post-mount or ip_down event?)
   ON_OFF=`cat $USEPATH/VPN_$IP_RANGE.txt` 

   if [ "$ON_OFF" = "1" ];then
      ACTION="OFF"
      logger -t "($(basename $0))" $$ "Current '$IP_NAME' tracking file is MARK=$ON_OFF (ON)"
   else     
      ACTION="ON"
      logger -t "($(basename $0))" $$ "Current '$IP_NAME' tracking file is MARK=$ON_OFF (OFF)"
   fi


fi


# Turn selective routing OFF
if [ "$ACTION" = "OFF" ];then
   ON_OFF=0
   logger -t "($(basename $0))" $$ VPN Selective routing for $IP_RANGE set MARK=$ON_OFF "(OFF)"
   echo "$IP_RANGE set MARK=$ON_OFF (OFF)"
   # Remove the selective rerouting....why ADD a new line with the mark set OFF?
   #iptables -t mangle -A PREROUTING -i br0 -m iprange --src-range $IP_RANGE -j MARK --set-mark $ON_OFF
   # .... why not simply delete the entire entry..but have to try all MARK entries!!!!
   iptables -t mangle -D PREROUTING -i br0 -m iprange --src-range $IP_RANGE -j MARK --set-mark 1
   #iptables -t mangle -D PREROUTING -i br0 -m iprange --src-range $IP_RANGE -j MARK --set-mark 2
fi

# Turn selective routing ON
if [ "$ACTION" = "ON" ];then
   ON_OFF=1
   logger -t "($(basename $0))" $$ VPN Selective routing for $IP_RANGE set MARK=$ON_OFF "(ON)"
   
   # Enable the selective rerouting
   # Prevent duplicate selective routing rule entries
   iptables -t mangle -D PREROUTING -i br0 -m iprange --src-range $IP_RANGE -j MARK --set-mark $ON_OFF
   iptables -t mangle -A PREROUTING -i br0 -m iprange --src-range $IP_RANGE -j MARK --set-mark $ON_OFF
   # Example for routing a specific port via VPN
   # iptables -t mangle -A PREROUTING -i br0 -m iprange --src-range $IP_RANGE -p tcp --dport ppppp -j MARK --set-mark $ON_OFF
   echo "$IP_RANGE set MARK=$ON_OFF (ON)"
fi

# Optionally FORCE the use of the VPN tunnel, so if the VPN tunnel drops, the device will not use the unencrypted default WAN
if [ "$FORCE" = "FORCE" ];then
   logger -t "($(basename $0))" $$ VPN Selective routing for $IP_RANGE WAN access blocked
   echo "$IP_RANGE WAN access blocked"
   # Prevent duplicate blocking rule entries
   iptables -D FORWARD -i br0 -s $IP_RANGE -o eth0 -j DROP
   iptables -I FORWARD -i br0 -s $IP_RANGE -o eth0 -j DROP
fi
# Allow removing of the WAN blocking if it was previously set
if [ "$FORCE" = "NOFORCE" ];then
   logger -t "($(basename $0))" $$ VPN Selective routing for $IP_RANGE WAN access allowed
   echo "$IP_RANGE WAN access allowed"
   iptables -D FORWARD -i br0 -s $IP_RANGE -o eth0 -j DROP
fi


# Track known status of VPN selective routing.....
echo $ON_OFF > $USEPATH/VPN_$IP_RANGE.txt


# Debug the routing tables
/jffs/scripts/IPTablesDump.sh "VPN_Client_$IP_RANGE-$ACTION"
exit


Regards,
 
Thank you very much Martineau for sharing this. One point, you said you choose to call this script from your custom OpenVPN client 'UP' script. Does that mean that if for some reason your OPENVPN does not go up, your script will not be run and traffic might leak through the regular ISP ?

firewall-start option is nice but I haven't found a handy way to remove that iptables rule on request without having to telnet and send the command iptables -D FORWARD -i br0 -o eth0 -j DROP

Best Regards
 
Thank you very much Martineau for sharing this. One point, you said you choose to call this script from your custom OpenVPN client 'UP' script. Does that mean that if for some reason your OPENVPN does not go up, your script will not be run and traffic might leak through the regular ISP ?

firewall-start option is nice but I haven't found a handy way to remove that iptables rule on request without having to telnet and send the command iptables -D FORWARD -i br0 -o eth0 -j DROP

Best Regards

My script was designed to be as flexible as possible and can be invoked with the appropriate argument to allow/deny use of 'un-encrypted' WAN access from wan-start or firewall-start etc.

To be honest, I am not in a geographical location where I feel the need to obfuscate my internet activities, but rather the script was originally used as a crude parental control ;)

i.e. a simple cron job can be scheduled to allow/deny WAN access or on adhoc demand via SSH..depending on circumstances etc.

If the approprite WAN blocking rule is applied before the wan-start event fires then you may be protected against leaks but I recall RMerlin stating that the order of script execution (apart from init-start) cannot be guaranteed...although this may no longer be the case.


P.S. Not sure if I understand your concern regarding a 'handy' way to remove/implement the WAN blocking rules :confused:


Regards,
 

Similar threads

Support SNBForums w/ Amazon

If you'd like to support SNBForums, just use this link and buy anything on Amazon. Thanks!

Sign Up For SNBForums Daily Digest

Get an update of what's new every day delivered to your mailbox. Sign up here!
Back
Top