Block all non VPN traffic on DD-WRT

Posted on

Problem :

I have a router with DD-WRT installed. Just got Open VPN configured on it. Works great.

I would now like to make it so that if the VPN tunnel goes down all traffic is blocked, nothing besides the VPN connection itself should ever go directly to the ISP. That is, the router should only allow communication going through the VPN.

Reading on several blogs I arrived at this line of code:

iptables -I FORWARD -i br0 -o eth1 -j DROP 

Which I have added to both startup and Firewall. But it does not seem to work. I have disabled the VPN and am still writing this question.

This is what I currently have. Which after several reebots does absolutely nothing.
enter image description here

If it matters, it’s a Asus RT-N16 router running firmware: DD-WRT v24-sp2 (12/20/11) mega

Current bridge (more if it helps info).
enter image description here

EDIT: I got this to work using the following firewall commands:

iptables -I FORWARD -i br0 -o tun0 -j ACCEPT
iptables -I FORWARD -i tun0 -o br0 -j ACCEPT
iptables -I FORWARD -i br0 -o vlan2 -j DROP
iptables -I INPUT -i tun0 -j REJECT
iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE

Wrote an article detailing how to use it in DD-WRT with OpenVPN to block all non VPN traffic here:

Solution :

Do you have OpenVPN as the endpoint on the wrt? The FORWARD rule won’t affect traffic originating on the Asus itself, only traffic which is sent on/over a different interface in which the Asus needs to route for. This Netfilter diagram can be helpful

Example (on your Linux workstation): add a logger for port 80 going out your WAN interface (might be eth0 on yours, I run a br0 bridge for virtulization):

# iptables -I FORWARD -o br0 -p tcp --dport 80 -j LOG --log-prefix="FWD: "

Now connect to a server which uses port 80

# wget -q -O /tmp/out.htm

Check your FORWARD chain:

# iptables -nvL FORWARD
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 LOG        tcp  --  *      br0              tcp dpt:80 LOG flags 0 level 4 prefix "FWD: "

Nothing.. dmesg is also quiet:

# dmesg | grep FWD:

Nothing shows.. so now try the OUTPUT chain instead:

# iptables -I OUTPUT -o br0 -p tcp --dport 80 -j LOG --log-prefix="OUT: "

After you repeat the wget, you should now see this:

    # dmesg | grep OUT
    [427898.519765] OUT: IN= OUT=br0 SRC= DST= LEN=52 TOS=0x00 PREC=0x00 TTL=64 ID=62284 DF PROTO=TCP SPT=58982 DPT=80 WINDOW=242 RES=0x00 ACK URGP=0 

Dropping egress TCP everything now becomes a simple rule which could look like this. You could also leave out the -p tcp to block any IP traffic this is just an example:

# iptables -I OUTPUT -o br0 -p tcp -j REJECT --reject-with icmp-host-prohibited

# wget -O /tmp/foo
converted '' (ANSI_X3.4-1968) -> '' (UTF-8)
--2017-02-14 12:38:00--
Resolving (, 2607:f8b0:4009:80c::2004
Connecting to (||:80... failed: No route to host.
Connecting to (|2607:f8b0:4009:80c::2004|:80... failed: Address family not supported by protocol.

Leave a Reply

Your email address will not be published. Required fields are marked *