What's new

Redirect Internet traffic misbehaving

  • 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!

If 'Start with WAN' is unset, the settings are completely ignored. I personally don't fee that this is should be considered a bug, as the user made the change. (I just wasn't anticipating it.) If the user were also obliged to delete all policy rules too, it would seem onerous.

On the other hand, if the client doesn't start due to (e.g.) authentication failing because of a bad certificate, the RPDB and (some) table 111 rules are in place, effectively blocking the specified client. The table appears as:
Code:
104.175.4.1 dev vlan2  scope link
192.168.0.0/24 dev br0  proto kernel  scope link  src 192.168.0.1
104.175.4.0/22 dev vlan2  proto kernel  scope link  src 104.175.4.205
127.0.0.0/8 dev lo  scope link
prohibit default

The other entries into table 111 must, as you surmise, be based on some assessment of success. This finally explains to me why I saw only those 5 lines when custom config options were creating errors. My [PUSH-OPTIONS] errors must have precluded the finalization of table 111.

As you say, now I must look at port forwarding again, which is still failing for me. Another thread...
 
How can I query across the tunnel from the router? Specifying interface for curl requests now fails. For example, the following used to work:
Code:
curl -v --interface tun11 checkip.dyndns.com
* About to connect() to checkip.dyndns.com port 80 (#0)
*  Trying 91.198.22.70... Local Interface tun11 is ip 10.171.1.6 using address family 2
* Local port: 0
* Connection timed out
*  Trying 216.146.38.70... Local Interface tun11 is ip 10.171.1.6 using address family 2
* Local port: 0
* Connection timed out
*  Trying 216.146.43.70... Local Interface tun11 is ip 10.171.1.6 using address family 2
* Local port: 0
* Connection timed out
* couldn't connect to host
* Closing connection #0
curl: (7) couldn't connect to host

Edit: Updated with verbose
 
Last edited:
Only vlan2 and tun11 actually allow binding. vlan2 successfully reports the WAN IP using the above URL. Unsure what is blocking VPN traffic.
Code:
ifconfig |grep -E "^[e|v|t]" |cut -d" " -f1 |while read line; do echo $line; curl --interface $line checkip.dyndns.com; done
 
To summarize my last 2 posts, one cannot query across the tunnel interface unless Redirect != Policy Rules and 'route-nopull' is absent. Else, this will time out:
Code:
curl -v --interface tun11 checkip.dyndns.com
curl: (7) couldn't connect to host

The problem is that the router is using table 254 (which is stripped of any VPN routing when using Policy Rules or nopull) and the packet never leaves. I was hoping the solution was as elegant as
Code:
ip rule add oif tun11 table 111

It's not :(. Instead, I have a very clunky function that uses nslookup to find all addresses for the curl target and temporarily adds rules for them to table 254.
Code:
#    this function and 3 vars are normally defined elsewhere (in a library )
    logerror(){ echo "$*"; }
    tun_if=tun11
    tun_p2p=10.105.1.5
    debugme=y

    curl11(){
        curl11=
        if [ -z "$tun_p2p" ]; then
            if ! get_ifip $tun_if tun_ip tun_pub tun_p2p; then
                logerror "Unable to send request"
                return 1
            fi
        fi
     
        local url="$1"
        local srv="$(echo "$1" |cut -d: -f2)"
        [ "${srv:0:2}" = // ] && srv="${srv:2}"
        srv="${srv%%/*}"

        local fn=/tmp/11-curl
        rm -f $fn

        nslookup "$srv" 2>/dev/null |grep -E "^Address " |while read line; do
            if [ "${line:11:3}" != 127 ]; then
                echo "$line" |cut -d" " -f3 >> $fn
            fi
        done
     
        if [ ! -s $fn ]; then
            logerror "Unable to resolve target address(es)"
            return 1
        fi
     
        local data=
        [ "$2" ] && data="-d \"$2\""

        while read line; do
            [ "$debugme" ] && echo "adding $line via $tun_p2p"
            ip route add "$line" via $tun_p2p dev $tun_if
        done < $fn
     
        [ "$debugme" ] && set -x
        curl11="$(curl --interface $tun_if $data "$1" 2> /dev/null)"
        { set +x; } 2>/dev/null
     
        while read line; do
            ip route del "$line" via $tun_p2p dev $tun_if
        done < $fn
    }

    curl11 checkip.dyndns.com
    echo "rc='$(echo "$curl11" |grep -oE "[0-9][0-9\.]+")'"
 
    curl11 http://ipecho.net/plain
    echo "rc='$curl11'"

There MUST be a better, simpler way. Can someone point me in the right direction?
 
Last edited:
using table 254 (which is stripped of any VPN routing when using Policy Rules or nopull) and the packet never leaves.

[/CODE]

Working as designed. ;)

If you list the RPDB rules, then this determines which table is used for a target IP or subnet destination.

As you have stated table 254 (aka main) will have no tun11 reference if Policy Rules is enabled as RMerlin clones table 254 to table 111 then removes the VPN server supplied routing entries from table 254.
However if you also specifiy 'route-nopull', then RMerlin's script /usr/sbin/vpnroute.sh blindly clones table 254 (that is now unfortunately missing the vital VPN routes) and table 111 has no 'default' statement so everything will incorrectly go via the WAN.


I am still unclear of your latest objective - i.e. are you asking for Selective VPN Routing by URL?

i.e. you want ALL requests from your LAN destined for say www.youtube.com to go via the VPN then you would logically expect to simply issue a single command (if Policy Routing is correctly enabled/configured!)

Code:
  ip rule add from 192.168.1.1/24 to www.youtube.com lookup 111

but unfortunately www.youtube.com in this context is syntactically invalid and seemingly cannot be automatically resolved to all valid YouTube IP addresses etc. - hence your nslookup script, and whilst a lengthy 254 table shouldn't be an issue, I don't think you will comprehensively always resolve all IP addresses, as you could get different results depending when you execute your script.

I believe the 'elegant' solution is to use ipset and dnsmasq

e.g. two dnsmasq directives

Code:
server=/youtube.com/8.8.8.8
ipset=/youtube.com.com/Client_VPN1

then using the same technique as Selective port-based Routing, you can tag the ipset with the appropriate fwmark

Code:
iptables -t mangle -A PREROUTING -i br0 -m set --set Client_VPN1 dst -j MARK --set-mark 16
ip rule add from 192.168.1.1/24 fwmark 16 lookup 111
ipset -N Client_VPN1 iphash

So once these three 'static' commands are in place, it should be a simple matter to add additional Selective Routing VPN URLs to dnsmasq.conf.add at your leisure! :cool:

e.g.

Code:
server=/netflix.com/8.8.8.8
ipset=/netflix.com/Client_VPN1

and restart service_dnsmasq

There is/was a thread that provides more detail, but the use of the dnsmasq ipset tagging method may not be available on all routers?

EDIT: The dnsmasq ipset directive does dynamically resolve/populate Client_VPN1 using firmware 380.57 on RT-AC68U

FYI, as per your post #6

http://www.snbforums.com/threads/redirect-internet-traffic-misbehaving.29351/#post-229887

I confirm that openvpn-event still doesn't seem to be consistently passed any args (for me at least) hence I personally still regard it to be unreliable, but having said that, if I modify RMerlin's vpnrouting.sh script

Code:
run_custom_script(){
if [ -f /jffs/scripts/openvpn-event ]
then
###################################################################### Martineau HACK!
#logger -t "custom script" "Running /jffs/scripts/openvpn-event (args: $PARAM)"
#sh /jffs/scripts/openvpn-event $PARAM
logger -t "custom script" "Running /jffs/scripts/openvpn-event (args: "$dev $script_type")"
sh /jffs/scripts/openvpn-event $dev $script_type
###################################################################### Martineau HACK!
fi
}

then I can spoof the passing of two relevant args to openvpn-event. :eek:

Might be an ARM router 380.57 regression?o_O
 
Last edited:
I am still unclear of your latest objective
Following all presumes Policy Blocking mode:

Objective 1: I would like to find out the VPN's public IP. However, the first 2 both return the WAN's public IP and the 3rd times out
Code:
curl ipecho.net/plain
curl --interface $ifconfig_local ipecho.net/plain
curl --interface tun11 ipecho.net/plain
curl: (7) couldn't connect to host
(wget --bind-address $ifconfig_local someurl.com also travels over the WAN)

Objective 2: I need to send a request to my VPN provider after the tunnel is established (in order to get a port). The request must go through the tunnel, else it gets rejected. I am not trying to have all traffic to their website follow the VPN for all LAN clients- just a particular request I initiate in script.​

I can dynamically add routes to 254 for all possible IP addresses and then clean them up (the curl11 function above). The cleanup is necessary for both the LAN clients and in case I wish to, for example, subsequently query those URLs without using the VPN. I suspect, however, that there's a much more elegant solution that is not destination-based utilizing the fact that these requests are only originating from the router.

I could even skip the nslookup functionality and send everything out the VPN (including LAN traffic) with
Code:
ip route add 0/1 via $route_vpn_gateway dev $dev
ip route add 128/1 via $route_vpn_gateway dev $dev
# curl away
ip route del 0/1 via $route_vpn_gateway dev $dev
ip route del 128/1 via $route_vpn_gateway dev $dev
Simple and terrible.
 
Code:
run_custom_script(){
if [ -f /jffs/scripts/openvpn-event ]
then
###################################################################### Martineau HACK!
#logger -t "custom script" "Running /jffs/scripts/openvpn-event (args: $PARAM)"
#sh /jffs/scripts/openvpn-event $PARAM
logger -t "custom script" "Running /jffs/scripts/openvpn-event (args: "$dev $script_type")"
sh /jffs/scripts/openvpn-event $dev $script_type
###################################################################### Martineau HACK!
fi
}

ps, Whether or not vpnrouting.sh passes arguments, if openvpn-event and any subsequent scripts are called by the openvpn service (which is always the use case), $script_type is available in the environment and doesn't need to be passed.

I'm no longer examining args passed except as a failover
 
Last edited:
I intend to use this but wonder how I best configure it.
Using Martineau modification, and modify vpnrouting.sh file.
How do I get the VPN IP number? with "curl -v --interface tun11 checkip.dyndns.com"
Do you have any configuration examples?

thanks
 
I intend to use this but wonder how I best configure it.
Using Martineau modification, and modify vpnrouting.sh file.
How do I get the VPN IP number? with "curl -v --interface tun11 checkip.dyndns.com"
Do you have any configuration examples?

thanks
The curl11 function I posted above will allow you to query any URL via the tunnel even if normal routing is through the ISP. (I have more robust code to handle nslookup failing if you run into that.) Just ensure that tun_if and tun_p2p are defined or rewrite with your own var names. You can scrap all logerror() or get_ifip() function calls too.

It is perfectly functional. I'm just hoping someone has a better solution or implementation. Unfortunately, @Martineau 's (quite elegant) dnsmasq technique means that I'm no longer able to query those URLs on another interface. Not in keeping with what I'm trying to achieve.
 
I have changed "tun_if = tun12" "tun_p2p = 10.128.x.xx" so it suits my own var names.
I have run it but get too much information out there just want to use vpn_ip, i get 10 rows as result.
Can you show your nslookup script, maby i can use it or part of it.

Thanks
 
@octopus The nslookup is already part of curl11 above. It outputs pertinent addresses to /tmp/11-curl
Code:
        local fn=/tmp/11-curl
        rm -f $fn

        nslookup "$srv" 2>/dev/null |grep -E "^Address " |while read line; do
            if [ "${line:11:3}" != 127 ]; then
                echo "$line" |cut -d" " -f3 >> $fn
            fi
        done

What gets returned is what gets returned... In the case of checkip.dyndns.com, it's a web page, so I parse it:
Code:
curl11 checkip.dyndns.com
echo $curl11
<html><head><title>Current IP Check</title></head><body>Current IP Address: 172.98.67.15</body></html>
vpn_ip=$(echo "$curl11" |grep -oE "[0-9][0-9\.]+")'"

Try ipecho.net/plain - it loads faster and doesn't require parsing
 
Last edited:
Code:
iptables -t mangle -A PREROUTING -i br0 -m set --set Client_VPN1 dst -j MARK --set-mark 16
ip rule add from 192.168.1.1/24 fwmark 16 lookup 111
ipset -N Client_VPN1 iphash
and restart service_dnsmasq
@Martineau I was trying to make the above work, but my lack of understanding around dnsmasq is definitely hindering me. I wanted to make ip sets where I can add and delete the rule as needed. e.g.
Code:
iptables -t mangle -A PREROUTING -i br0 -m set --set Switcheroo dst -j MARK --set-mark 128
ipset -N Switcheroo iphash
with /jffs/configs/dnsmasq.conf.add like this (I assume the IPs are authoritative nameservers for the domain, or can they be any DNS servers?)
Code:
server=/checkip.dyndns.com/208.78.70.100
ipset=/checkip.dyndns.com/Switcheroo
server=/ipecho.net/216.69.185.23/208.109.255.23
ipset=/ipecho.net/Switcheroo
server=/www.privateinternetaccess.com/208.78.70.28
ipset=/www.privateinternetaccess.com/Switcheroo
Then, I could
Code:
ip rule add from 192.168.1.1/24 fwmark 128 lookup 111
curl --interface tun11 ipecho.net/plain
ip rule del from 192.168.1.1/24 fwmark 128 lookup 111
However, if I issue service restart_dnsmasq or equivalent (like restart VPN), I lose all ability to resolve addresses, on the router or LAN. e.g. nslookup yahoo.com fails.
 
Are you determined to use curl? Just had an idea...why not just pull it from the routing table....(if I understand correctly that you are trying to get the external VPN WAN address)

ip route show table 111 | grep "via $(nvram get wan0_gateway)" | awk -F' ' '{ print $1 }'
 
@john9527 If you're asking me, getting the VPN ID is just one use case for using curl. My primary objective concerns a requirement of my VPN provider's port forwarding service. They need an hourly request to confirm the port they are forwarding. It must come via the tunnel.
 
@octopus The nslookup is already part of curl11 above. It outputs pertinent addresses to /tmp/11-curl
Code:
        local fn=/tmp/11-curl
        rm -f $fn

        nslookup "$srv" 2>/dev/null |grep -E "^Address " |while read line; do
            if [ "${line:11:3}" != 127 ]; then
                echo "$line" |cut -d" " -f3 >> $fn
            fi
        done

What gets returned is what gets returned... In the case of checkip.dyndns.com, it's a web page, so I parse it:
Code:
curl11 checkip.dyndns.com
echo $curl11
<html><head><title>Current IP Check</title></head><body>Current IP Address: 172.98.67.15</body></html>
vpn_ip=$(echo "$curl11" |grep -oE "[0-9][0-9\.]+")'"

Try ipecho.net/plain - it loads faster and doesn't require parsing

I removed dyndns.com and using ipecho.net and it give less rows.
In /tmp/11-curl gives me wrong vpn-ipnumber, give me: "adding 146.2xx.xx.x via 10.128.0.22" (bold one in 11-curl file)
But show right ip-number in: + curl11=46.2xx.xx.xxx rc='46.2xx.xx.xxx'

thanks!
 
Last edited:
@Martineau I was trying to make the above work, but my lack of understanding around dnsmasq is definitely hindering me. I wanted to make ip sets where I can add and delete the rule as needed. e.g.
Code:
iptables -t mangle -A PREROUTING -i br0 -m set --set Switcheroo dst -j MARK --set-mark 128
ipset -N Switcheroo iphash
with /jffs/configs/dnsmasq.conf.add like this (I assume the IPs are authoritative nameservers for the domain, or can they be any DNS servers?)
Code:
server=/checkip.dyndns.com/208.78.70.100
ipset=/checkip.dyndns.com/Switcheroo
server=/ipecho.net/216.69.185.23/208.109.255.23
ipset=/ipecho.net/Switcheroo
server=/www.privateinternetaccess.com/208.78.70.28
ipset=/www.privateinternetaccess.com/Switcheroo
Then, I could
Code:
ip rule add from 192.168.1.1/24 fwmark 128 lookup 111
curl --interface tun11 ipecho.net/plain
ip rule del from 192.168.1.1/24 fwmark 128 lookup 111
However, if I issue service restart_dnsmasq or equivalent (like restart VPN), I lose all ability to resolve addresses, on the router or LAN. e.g. nslookup yahoo.com fails.

I added the same entries to dnsmasq.conf.add

Then immediately after I create the ipset...


Code:
Name: Switcheroo

Type: iphash
References: 2
Header: hashsize: 1024 probes: 8 resize: 50
Members:

I then access URL

checkip.dyndns.com

via Firefox and the ipset now contains

Code:
Name: Switcheroo

Type: iphash
References: 2
Header: hashsize: 1024 probes: 8 resize: 50
Members:
216.146.38.70
216.146.43.70
91.198.22.70

I then access URL

ipecho.net

via Firefox and the ipset now contains


Code:
Name: Switcheroo

Type: iphash
References: 2
Header: hashsize: 1024 probes: 8 resize: 50
Members:
216.146.38.70
216.146.43.70
146.255.36.1
91.198.22.70

As expected I can't access URL

www.privateinternetaccess.com

and consequently the ipset remains unchanged.

Checking the tagging shows that it has fired 63 times....

Code:
Chain PREROUTING (policy ACCEPT 3335 packets, 661K bytes)

num  pkts bytes target  prot opt in  out  source  destination
1  78  5650 MARK  all  --  !vlan2 *  0.0.0.0/0  xxx.xxx.xxx.xxx MARK set 0xb400
2  63  6013 MARK  all  --  br0  *  0.0.0.0/0  0.0.0.0/0 match-set Switcheroo dst MARK set 0x80

So if table 111 is invalid I would expect ALL routes to fail, but dnsmasq isn't breaking on my system when applying your amendments....did you see any dnsmasq initialisation error messages in Syslog?

P.S. I assume you have already simply tried

curl -v --interface xxx.xxx.xxx.xxx checkip.dyndns.com

rather than specify the VPN interface?
 
Last edited:
@octopus, the rows in /tmp/11-curl should be of no interest to you, simply the value assigned to $curl11. Those rows are there to ensure that the curl successfully resolves on any of the URL's possible IP addresses- they relate to your curl target, not the response. (@john9527 's parsing is even easier, if the external ip is your only requirement for curl.)

@Martineau, Yes, I saw openvpn errors before, service restart_dnsmasq makes them clearer
Code:
Jan 15 09:44:44 custom config: Appending content of /jffs/configs/dnsmasq.conf.add.
Jan 15 09:44:44 dnsmasq[2632]: recompile with HAVE_IPSET defined to enable ipset directives at line 20 of /etc/dnsmasq.conf
Jan 15 09:44:44 dnsmasq[2632]: FAILED to start up

ipset appears to be loaded
Code:
lsmod | grep -E "ipt_|ip_"
ip_set_iptreemap        8207  0
ip_set_iphash           6237  1
ipt_set                  901  3
ip_set                 11188  5 ip_set_iptreemap,ip_set_iphash,ipt_set

@ your ps, It's not clear, but in post 26, I lamented that curl --interface 10.x.y.z checkip.dyndns.com where 10.x.y.z=$ifconfig_local, simply returns the WAN'S IP, indicating that it does not traverse the tunnel.
 
Last edited:
@octopus, the rows in /tmp/11-curl should be of no interest to you, simply the value assigned to $curl11. Those rows are there to ensure that the curl successfully resolves on any of the URL's possible IP addresses- they relate to your curl target, not the response. (@john9527 's parsing is even easier, if the external ip is your only requirement for curl.)

@Martineau, Yes, I saw openvpn errors before, service restart_dnsmasq makes them clearer
Code:
Jan 15 09:44:44 custom config: Appending content of /jffs/configs/dnsmasq.conf.add.
Jan 15 09:44:44 dnsmasq[2632]: recompile with HAVE_IPSET defined to enable ipset directives at line 20 of /etc/dnsmasq.conf
Jan 15 09:44:44 dnsmasq[2632]: FAILED to start up

ipset appears to be loaded
Code:
lsmod | grep -E "ipt_|ip_"
ip_set_iptreemap        8207  0
ip_set_iphash           6237  1
ipt_set                  901  3
ip_set                 11188  5 ip_set_iptreemap,ip_set_iphash,ipt_set

@ your ps, It's not clear, but in post 26, I lamented that curl --interface 10.x.y.z checkip.dyndns.com where 10.x.y.z=$ifconfig_local, simply returns the WAN'S IP, indicating that it does not traverse the tunnel.

Sadly I rely on the following command to determine if dnsmasq supports ipset :)

Code:
dnsmasq    -v
 

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!
Top