Tutorial [SOLUTION] OpenVPN Client Split Tunnel Reverse Proxy Web Traffic using Nginx, DNSMasq, and IPTables

  • ATTENTION! As of November 1, 2020, you are not able to reply to threads 6 months after the thread is opened if there are more than 500 posts in the thread.
    Threads will not be locked, so posts may still be edited by their authors.
    Just start a new thread on the topic to post if you get an error message when trying to reply to a thread.

garycnew

Occasional Visitor
Works Great! Need Testers! Need more than 10K Characters per Post!

Requirements/Assumptions:

1. An Asuswrt-Merlin Compatible Router (i.e., Asus RT-AC66U)
2. Asuswrt-Merlin Compatible Firmware (i.e., 384.19)
3. Established OpenVPN Client Connection (Force Internet traffic through tunnel: Policy Rules)
4. Formated JFFS Partition and Enabled JFFS Custom Scripts and Configs
5. Entware Installed via Asuswrt-Merlin Terminal Menu (AMTM)
6. Nginx Installation with DNSMasq and IPTables Configuration (/opt/etc/nginx/nginx.conf)
7. Capable of Editing the following User Scripts:
/jffs/configs/dnsmasq.conf.add
/jffs/scripts/lighttpd.postconf
/jffs/scripts/nat-start
/jffs/scripts/post-mount

Code:
# /usr/sbin/ip addr add 192.168.0.2/24 brd + dev br0:0
# /usr/sbin/ip addr add 192.168.0.3/24 brd + dev br0:1

# /usr/sbin/ip ad
11: br0: <BROADCAST,MULTICAST,ALLMULTI,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN
    link/ether c0:56:27:d1:b8:a4 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.1/24 brd 192.168.0.255 scope global br0
    inet 192.168.0.2/24 brd 192.168.0.255 scope global secondary br0
    inet 192.168.0.3/24 brd 192.168.0.255 scope global secondary br0
README: Custom Domains with DNSMasq

LAN > DHCP Server > DNS and WINS Server Setting
DNS Server 1: [LAN_IP]
DNS Server 2: [EMPTY]
Advertise router's IP in addition to user-specified DNS: [No]
Code:
# vi /jffs/configs/dnsmasq.conf.add
address=/dnsleaktest.com/z1.fm/192.168.0.2
address=/dnsleak.com/audiobookbay.nl/192.168.0.3
Code:
# service restart_dnsmasq
Done.
From a Client Machine, confirm DNSMasq is working from the Command Prompt:
Code:
C:\Users\Name>ipconfig /flushdns
Windows IP Configuration
Successfully flushed the DNS Resolver Cache.

C:\Users\Name>ping dnsleaktest.com
Pinging dnsleaktest.com [192.168.0.2] with 32 bytes of data:
Reply from 192.168.0.2: bytes=32 time<1ms TTL=64
Reply from 192.168.0.2: bytes=32 time<1ms TTL=64
Ping statistics for 192.168.0.2:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 0ms, Maximum = 0ms, Average = 0ms

C:\Users\Name>ping dnsleak.com
Pinging dnsleak.com [192.168.0.3] with 32 bytes of data:
Reply from 192.168.0.3: bytes=32 time<1ms TTL=64
Reply from 192.168.0.3: bytes=32 time<1ms TTL=64
Ping statistics for 192.168.0.3:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 0ms, Maximum = 0ms, Average = 0ms
Code:
# vi /jffs/scripts/lighttpd.postconf
#!/bin/sh

# Force Lighttpd (Webdav) to Reload Modified Config
/usr/bin/killall lighttpd; sed -i 's/":443"/"192.168.0.1:443"/g' /tmp/lighttpd.conf && /usr/sbin/lighttpd -f /tmp/lighttpd.conf -D &
logger "Running /jffs/scripts/lighttpd.postconf"
Code:
# vi /jffs/scripts/nat-start
#!/bin/sh

sleep 10  # During the boot process nat-start may run multiple times so this is required

# Ensure Duplicate Rules are not Created
for VPN_ID in 0 1 2 3 4 5
   do
      ip rule del prio 999$VPN_ID  2>/dev/null
   done

# Create RPDB Rules
ip rule add from 0/0 fwmark "0x8000/0x8000" table main   prio 9990        # WAN   fwmark
ip rule add from 0/0 fwmark "0x7000/0x7000" table ovpnc4 prio 9991        # VPN 4 fwmark
ip rule add from 0/0 fwmark "0x3000/0x3000" table ovpnc5 prio 9992        # VPN 5 fwmark
ip rule add from 0/0 fwmark "0x1000/0x1000" table ovpnc1 prio 9993        # VPN 1 fwmark
ip rule add from 0/0 fwmark "0x2000/0x2000" table ovpnc2 prio 9994        # VPN 2 fwmark
ip rule add from 0/0 fwmark "0x4000/0x4000" table ovpnc3 prio 9995        # VPN 3 fwmark

# Force Lighttpd (Webdav) to Reload Modified Config
. /jffs/scripts/lighttpd.postconf

# Mark Outbound Web Services Packets from WAN to OpenVPN Client 1 and/or OpenVPN Client 2
iptables -t mangle -I OUTPUT -o vlan2 -p tcp -s 192.168.0.2/32 -j MARK --set-mark 0x1000/0x1000
iptables -t mangle -I OUTPUT -o vlan2 -p tcp -s 192.168.0.3/32 -j MARK --set-mark 0x2000/0x2000

# Mark Inbound Web Services Packets from OpenVPN Server to WAN
iptables -t mangle -I INPUT -i br0 -p tcp -d 192.168.0.2/32 -j MARK --set-mark 0x8000/0x8000
iptables -t mangle -I INPUT -i br0 -p tcp -d 192.168.0.3/32 -j MARK --set-mark 0x8000/0x8000
Code:
# service restart_webdav
Done.

# opkg install nginx-ssl
Installing nginx-ssl (1.19.2-1a) to root...
Downloading http://bin.entware.net/armv7sf-k2.6/nginx-ssl_1.19.2-1a_armv7-2.6.ipk
Configuring nginx-ssl.
Code:
# vi /opt/etc/nginx/nginx.conf
user nobody;
worker_processes auto;

events {
    worker_connections  512;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;

    keepalive_timeout  75;  # client
    keepalive_requests 100; # client

    server {
        listen                        192.168.0.2:80;
        server_name                   $host;

        root /opt/share/nginx/html;

        proxy_ssl_server_name         on; # sni

        location / {
            resolver 103.86.99.100;
            proxy_bind $server_addr;
            proxy_pass https://$host$request_uri;
            proxy_redirect https:// http://;
            proxy_set_header Accept-Encoding ""; # Needed by sub_filter to disable gzip compression
            sub_filter_types text/javascript text/css text/xml;
            sub_filter 'https:' 'http:';
            sub_filter_once off;
        }
    }

    server {
        listen                        192.168.0.3:80;
        server_name                   $host;

        root /opt/share/nginx/html;

        proxy_ssl_server_name         on; # sni

        location / {
            resolver 103.86.99.100;
            proxy_bind $server_addr;
            proxy_pass https://$host$request_uri;
            proxy_redirect https:// http://;
            proxy_set_header Accept-Encoding ""; # Needed by sub_filter to disable gzip compression
            sub_filter_types text/javascript text/css text/xml;
            sub_filter 'https:' 'http:';
            sub_filter_once off;
        }
    }

    # HTTPS Servers

    ssl_session_cache    shared:SSL:10m;
    ssl_session_timeout  10m;

    server {
        listen                        192.168.0.2:443 ssl;
        server_name                   $host;
        return 302                    http://$host$request_uri; # Redirect All HTTPS Requests to Nginx HTTP Listener

        ssl_certificate               /etc/cert.pem;
        ssl_certificate_key           /etc/key.pem;
        ssl_protocols                 TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers                   HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers     on;

        proxy_ssl_trusted_certificate /opt/etc/ssl/cert.pem;
        proxy_ssl_verify              on;
        proxy_ssl_verify_depth        2;
        proxy_ssl_session_reuse       on;

        proxy_ssl_server_name         on; # sni

        location / {
            resolver 103.86.99.100;
            proxy_bind $server_addr;
            proxy_pass https://$host$request_uri;
            proxy_redirect https:// http://;
            proxy_set_header Accept-Encoding ""; # Needed by sub_filter to disable gzip compression
            sub_filter_types text/javascript text/css text/xml;
            sub_filter 'https:' 'http:';
            sub_filter_once off;
        }
    }

    server {
        listen                        192.168.0.3:443 ssl;
        server_name                   $host;
        return 302                    http://$host$request_uri; # Redirect All HTTPS Requests to Nginx HTTP Listener

        ssl_certificate               /etc/cert.pem;
        ssl_certificate_key           /etc/key.pem;
        ssl_protocols                 TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers                   HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers     on;

        proxy_ssl_trusted_certificate /opt/etc/ssl/cert.pem;
        proxy_ssl_verify              on;
        proxy_ssl_verify_depth        2;
        proxy_ssl_session_reuse       on;

        proxy_ssl_server_name         on; # sni

        location / {
            resolver 103.86.99.100;
            proxy_bind $server_addr;
            proxy_pass https://$host$request_uri;
            proxy_redirect https:// http://;
            proxy_set_header Accept-Encoding ""; # Needed by sub_filter to disable gzip compression
            sub_filter_types text/javascript text/css text/xml;
            sub_filter 'https:' 'http:';
            sub_filter_once off;
        }
    }
}
Code:
# /opt/etc/init.d/S80nginx start
Nginx started.

# netstat -anp|grep :80
tcp        0      0 192.168.0.3:80          0.0.0.0:*               LISTEN      11919/nginx: master
tcp        0      0 192.168.0.2:80          0.0.0.0:*               LISTEN      11919/nginx: master
tcp        0      0 192.168.0.1:80          0.0.0.0:*               LISTEN      258/httpd

# netstat -anp|grep :443
tcp        0      0 192.168.0.3:443         0.0.0.0:*               LISTEN      11919/nginx: master
tcp        0      0 192.168.0.2:443         0.0.0.0:*               LISTEN      11919/nginx: master
tcp        0      0 192.168.0.1:443         0.0.0.0:*               LISTEN      10157/lighttpd
Code:
# vi /jffs/scripts/post-mount
#!/bin/sh

sleep 30

# Force Lighttpd (Webdav) to Reload Modified Config
. /jffs/scripts/lighttpd.postconf

# Add Virtual IP Addresses to br0
#/sbin/ifconfig br0:0 192.168.0.2
/usr/sbin/ip addr add 192.168.0.2/24 brd + dev br0:0
/usr/sbin/ip addr add 192.168.0.3/24 brd + dev br0:1

# start all Entware services
/opt/etc/init.d/rc.unslung start
NOTICE: If you appreciated this Tutorial, you might also like my Guide on [SOLVED] OpenVPN Client Split Tunnel for BitTorrent Traffic.
 
Last edited:

archiel

Regular Contributor
For us non-technical users, why might I want this - what sort of situations would this be helpful for?
 

L&LD

Part of the Furniture
Non-technical users wouldn't be asking this question. :)
 

archiel

Regular Contributor
Non-technical users wouldn't be asking this question. :)
I just did!!:) At this point I just know that I don't know. What I would like to know is what it is that I don't know.
 

garycnew

Occasional Visitor
For us non-technical users, why might I want this - what sort of situations would this be helpful for?
Hi archiel!

Excellent question! I was limited in the number of characters (10K) I was able to use in the original post, so I wasn't really able to describe the use cases for such an implementation.

In short, this tutorial shows you how to configure your Asuswrt-Merlin Router as a Reverse Proxy to allow you to browse specified websites through your existing OpenVPN Tunnel(s); while, the rest of your browsing experience traverses your normal Internet connection (Split-Tunneling).

This comes in handy when certain websites that are normally blocked based on geographical location, etc are suddenly available again via this process. The best part is that with Split-Tunneling, you no longer have to connect/disconnect your OpenVPN Tunnel each time you want to browse to the website(s) in question. You just leave it always on. I even show you how to configure your Asuswrt-Merlin Router to make use of more than one OpenVPN Split-Tunnel to browse from various countries/locations to different websites at the same time.

This tutorial is one of the reasons why one upgrades to Asuswrt-Merlin for features such as these.

Thanks for the question. Hope that helps.

Respectfully,


Gary

P.S. If you like this tutorial, you should checkout my tutorial on OpenVPN Client Split-Tunnel for BitTorrrent Traffic.
 
Last edited:

archiel

Regular Contributor
Hi Gary, that makes sense and I can see why I might want to use this if I had 'problem sites'.

Looking at the above, it seems to based around using192.168.0.2 & 192.168.0.3, is this on the assumption that 192.168.0.1 is the routers LAN IP, so if it was set to say 10.0.0.1, would you amend to 10.0.0.2 & 10.0.0.3 or is this irrelevant?

Also if it is based on the LAN IP, I assume that that the DHCP range needs to be modified to exclude these addresses and care would also need to ensure that they were not already in use (e.g. for Diversion with Pixelserv).

Thanks

archiel
 

garycnew

Occasional Visitor
Hi archiel!

You are precisely correct with both assumptions.
Looking at the above, it seems to based around using192.168.0.2 & 192.168.0.3, is this on the assumption that 192.168.0.1 is the routers LAN IP, so if it was set to say 10.0.0.1, would you amend to 10.0.0.2 & 10.0.0.3 or is this irrelevant?
The tutorial is based on a LAN IP of 192.168.0.1
Also if it is based on the LAN IP, I assume that that the DHCP range needs to be modified to exclude these addresses and care would also need to ensure that they were not already in use (e.g. for Diversion with Pixelserv).
The tutorial assumes you have excluded the Virtual IP's you will be using from any existing DHCP scope and are not in use by any other service.

It seems you are more technical than you let on. :)

Respectfully,


Gary
 

SomeWhereOverTheRainBow

Very Senior Member
Hi archiel!

You are precisely correct with both assumptions.


The tutorial is based on a LAN IP of 192.168.0.1


The tutorial assumes you have excluded the Virtual IP's you will be using from any existing DHCP scope and are not in use by any other service.

It seems you are more technical than you let on. :)

Respectfully,


Gary
so what is the advantage of this versus policy based routing using- x3mRouting ~ Selective Routing for Asuswrt-Merlin Firmware. Is the reverse proxy just a cleaner way of doing it?
 

SomeWhereOverTheRainBow

Very Senior Member
Works Great! Need Testers! Need more than 10K Characters per Post!

Requirements/Assumptions:

1. An Asuswrt-Merlin Compatible Router (i.e., Asus RT-AC66U)
2. Asuswrt-Merlin Compatible Firmware (i.e., 384.19)
3. Established OpenVPN Client Connection (Force Internet traffic through tunnel: Policy Rules)
4. Formated JFFS Partition and Enabled JFFS Custom Scripts and Configs
5. Entware Installed via Asuswrt-Merlin Terminal Menu (AMTM)
6. Nginx Installation with DNSMasq and IPTables Configuration (/opt/etc/nginx/nginx.conf)
7. Capable of Editing the following User Scripts:
/jffs/scripts/wan-event
/jffs/scripts/nat-start
/jffs/scripts/post-mount
/jffs/configs/dnsmasq.conf.add

Code:
# /usr/sbin/ip addr add 192.168.0.2/24 brd + dev br0:0
# /usr/sbin/ip addr add 192.168.0.3/24 brd + dev br0:1

# /usr/sbin/ip ad
11: br0: <BROADCAST,MULTICAST,ALLMULTI,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN
    link/ether c0:56:27:d1:b8:a4 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.1/24 brd 192.168.0.255 scope global br0
    inet 192.168.0.2/24 brd 192.168.0.255 scope global secondary br0
    inet 192.168.0.3/24 brd 192.168.0.255 scope global secondary br0

# vi /jffs/scripts/wan-event
#!/bin/sh

sleep 10  # During the boot process wan-start may run multiple times so this is required

if [ "$2" = "connected" ]; then
   #/sbin/ifconfig br0:0 192.168.0.2
   /usr/sbin/ip addr add 192.168.0.2/24 brd + dev br0:0
   /usr/sbin/ip addr add 192.168.0.3/24 brd + dev br0:1
fi
README: Custom Domains with DNSMasq

LAN > DHCP Server > DNS and WINS Server Setting
DNS Server 1: [LAN_IP]
DNS Server 2: [EMPTY]
Advertise router's IP in addition to user-specified DNS: [No]

Code:
# vi /jffs/configs/dnsmasq.conf.add
address=/dnsleaktest.com/z1.fm/192.168.0.2
address=/dnsleak.com/audiobookbay.nl/192.168.0.3

# service restart_dnsmasq
Done.
so hypothetically, you could route all web browsing traffic through the split tunnel using something like
Code:
address=/#/192.168.0.2
This may be benefitial if you are only trying to route your browsing traffic through the tunnel.
 

garycnew

Occasional Visitor
so what is the advantage of this versus policy based routing using- x3mRouting ~ Selective Routing for Asuswrt-Merlin Firmware. Is the reverse proxy just a cleaner way of doing it?
SomeWhereOverTheRainBow,

I believe the primary difference between Xentrx's x3mRouting Project and this Reverse Proxy implementation is Masquerade VPN Tunneling vs Proxy VPN Tunneling for a given LAN client.

Initially, I turned to Xentrx's x3mRouting Project as a solution for my needs and found it to be an excellent Masquerade VPN Tunneling management product. However, I wanted something that would permit Proxy VPN Tunneling for a given LAN client and work effortlessly with CDN based websites.

Additionally, Xentrx's x3mRouting Project seems to be focused more on streaming services; while, this Reverse Proxy implementation is geared more toward web browsing.

In short, I believe it just comes down to your particular need and the implementation that will work best for you.

Hope that answers your questions.

Respectfully,


Gary
 
Last edited:

garycnew

Occasional Visitor
so hypothetically, you could route all web browsing traffic through the split tunnel using something like
Code:
address=/#/192.168.0.2
This may be benefitial if you are only trying to route your browsing traffic through the tunnel.
SomeWhereOverTheRainBow,

I'm still fairly new with DNSMasq, but if you are able to use an any wildcard delimeter as you suggest; then, Yes... You could send all web traffic to the Reverse Proxy. However, that kind of defeats the purpose of the Split VPN Tunnel.

Respectfully,


Gary
 
Last edited:

Similar threads

Latest threads

Sign Up For SNBForums Daily Digest

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