What's new

IPTABLES command needed with OpenVPN client

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

GSpock

Senior Member
Hi falks,
I have set-up a TorGuard VPN client on my RT87U running Merlin 384.10_2 so that my Synology NAS is using this route.

After some googling and (some) TorGuard help, I need to issue the following command in order for my NAS to continue to be accessible from internet: (btw not sure in what order neither if all are really needed)

iptables -I FORWARD -i tun11 -p tcp -d mynas-ip --dport p1 -j ACCEPT
iptables -I FORWARD -i tun11 -p udp -d mynas-ip --dport p2 -j ACCEPT
iptables -I FORWARD -i tun11 -p tcp -d mynas-ip --dport p3 -j ACCEPT
iptables -t nat -I PREROUTING -i tun11 -p tcp --dport p1 -j DNAT --to-destination mynas-ip
iptables -t nat -I PREROUTING -i tun11 -p udp --dport p2 -j DNAT --to-destination mynas-ip
iptables -t nat -I PREROUTING -i tun11 -p tcp --dport p3 -j DNAT --to-destination 1mynas-ip

I am now wondering where those statement should be best executed ? I tried in a nat-start script, but this has completely block my entire internet access :eek: .... until I issue a "service restart_firewall" command o_O

Any suggestions ?
Thanks,
GS
 
Last edited:
Hi falks,
I have set-up a TorGuard VPN client on my RT87U running Merlin 384.10_2 so that my Synology NAS is using this route.

After some googling and (some) TorGuard help, I need to issue the following command in order for my NAS to continue to be accessible from internet: (btw not sure in what order neither if all are really needed)

iptables -I FORWARD -i tun11 -p tcp -d mynas-ip --dport p1 -j ACCEPT
iptables -I FORWARD -i tun11 -p udp -d mynas-ip --dport p2 -j ACCEPT
iptables -I FORWARD -i tun11 -p tcp -d mynas-ip --dport p3 -j ACCEPT
iptables -t nat -I PREROUTING -i tun11 -p tcp --dport p1 -j DNAT --to-destination mynas-ip
iptables -t nat -I PREROUTING -i tun11 -p udp --dport p2 -j DNAT --to-destination mynas-ip
iptables -t nat -I PREROUTING -i tun11 -p tcp --dport p3 -j DNAT --to-destination 1mynas-ip

I am now wondering where those statement should be best executed ? I tried in a nat-start script, but this has completely block my entire internet access ....

Any suggestions ?
Thanks,
GS
My guess is you need two lines for each port. One line for tcp and another for udp. Before each line, add a line to remove any existing entries to prevent duplicate entries from being created

Code:
iptables -D FORWARD -i tun11 -p tcp -d mynas-ip --dport p1 -j ACCEPT
iptables -I FORWARD -i tun11 -p tcp -d mynas-ip --dport p1 -j ACCEPT

iptables -D FORWARD -i tun11 -p udp -d mynas-ip --dport p1 -j ACCEPT
iptables -I FORWARD -i tun11 -p udp -d mynas-ip --dport p1 -j ACCEPT

Create a script containing the commands and test.

Once you get it working, you can execute the script from /jffs/scripts/nat-start so it runs at boot. We may need to add some lock code logic to the script as nat-start can at times run concurrently which can create havoc depending on what you are trying to do. Unfortunately, iptables falls into this category.
 
Last edited:
My guess is you need two lines for each port. One line for tcp and another for udp. Before each line, add a line to remove any existing entries to prevent duplicate entries.

Code:
iptables -D FORWARD -i tun11 -p tcp -d mynas-ip --dport p1 -j ACCEPT
iptables -I FORWARD -i tun11 -p tcp -d mynas-ip --dport p1 -j ACCEPT

iptables -D FORWARD -i tun11 -p udp -d mynas-ip --dport p1 -j ACCEPT
iptables -I FORWARD -i tun11 -p udp -d mynas-ip --dport p1 -j ACCEPT

Create a script containing the commands and test.

Once you get it working, you can execute the script from /jffs/scripts/nat-start so it runs at boot.

Thanks. When I do it in a nat-start script, it blocks all my internet access .... note that the command with the PREROUTING is also needed, while port 1 & 3 is TCP only, port 2 UDP only
 
Thanks. When I do it in a nat-start script, it blocks all my internet access .... note that the command with the PREROUTING is also needed, while port 1 & 3 is TCP only, port 2 UDP only
Acknowledged. I am pecking away on a iPad and too much work to copy/paste and edit all of the lines for each port. :confused:

If the script is working okay when you run from a command line, Search in the system log for nat-start and see if there are concurrent instances running at the same time. I can post some lock file code tomorrow you can add to the script to see if that helps. The delete lines before the insert and append lines will also help prevent duplicate entries.
 
Acknowledged. I am pecking away on a iPad and too much work to copy/paste and edit all of the lines for each port. :confused:

If the script is working okay when you run from a command line, Search in the system log for nat-start and see if there are concurrent instances running at the same time. I can post some lock file code tomorrow you can add to the script to see if that helps. The delete lines before the insert and append lines will also help prevent duplicate entries.

OK - thanks, no problem.
if I have a /jffs/scripts/nat-start file, then indeed I can see in the syslog file that it is executed when the firewall restart ... looking forward your code and thanks for your time.

GS
 
.... if the first line of my nat-start script is #!/bin/sh, then it blocks all my internet access until the file is remove and the firewall restarted.
when I remove this line, the script run, I have access to internet BUT the iptables commands are not taken into account (iptables -L) ==> side effect, NAS not available from internet.

Any furhter ideas ?
 
No it doesn't. It tries to run script but fails because you have removed the first line (#!/bin/sh).
Thanks, indeed, that is why it does nothing :eek:.
Quite strange that when I run the commands manually, it is all OK (ps: yes, the script has the execute feature) ; BTW, is nat-start the right place to run those commands ?
 
Quite strange that when I run the commands manually, it is all OK (ps: yes, the script has the execute feature) ; BTW, is nat-start the right place to run those commands ?

The Linux shell needs to be told what program to use to run the script. A script could be shell-based, Perl, Python, etc... That first line tells to execute the script as a shell script.
 
The Linux shell needs to be told what program to use to run the script. A script could be shell-based, Perl, Python, etc... That first line tells to execute the script as a shell script.

OK thanks, I got that.
How do you explain then when nat-start script (with the #!/bin/sh in the first line) is there with the iptables commands, it screw-up all my internet access ... ? Any suggestion on what to do ?
Rgds,
GS
 
Instead of managing these via a nat startup script, why not use the OpenVPN scripting engine? When the routes come up and the route-up event is triggered, you add the port forwards. When the OpenVPN comes down, and the route-pre-down event occurs, you delete the port forwards.

I suppose, alternatively, you could use the up and down events as triggers instead.

That would actually make more sense since the port forwards are only valid during the time the OpenVPN client is up and running. And you eliminate all the timing issues.

You can also generalize the rules so they work w/ any OpenVPN client. When the OpenVPN client triggers the event, your script is passed the dev name (e.g., tun11) as an environment variable ($dev). So you could write the rules as follows.

Code:
iptables -I FORWARD -i $dev -p tcp -d mynas-ip --dport p1 -j ACCEPT
iptables -I FORWARD -i $dev -p udp -d mynas-ip --dport p2 -j ACCEPT
iptables -I FORWARD -i $dev -p tcp -d mynas-ip --dport p3 -j ACCEPT
iptables -t nat -I PREROUTING -i $dev -p tcp --dport p1 -j DNAT --to-destination mynas-ip
iptables -t nat -I PREROUTING -i $dev -p udp --dport p2 -j DNAT --to-destination mynas-ip
iptables -t nat -I PREROUTING -i $dev -p tcp --dport p3 -j DNAT --to-destination 1mynas-ip
 
Last edited:
Instead of managing these via a nat startup script, why not use the OpenVPN scripting engine?

Thanks.
where should that script be located and how should it be triggered ???

Coming back to my initial request: the 6 iptables commands are running fine from command line when connected via SSH on the router, but when I put them in a /jffs/scripts/nat-start, then the router goes crazy and all my internet access is blocked until I remove the nat-start file and issue a "service restart_firewall".
My assumption is that nat-start is the place to put hose commands, but so far no one gave me a clue if this is correct.

In the meantime, I have to manually issue the iptables commands manually otherwise my NAS is no more accessible from the internet (and yes, the VPN provider allows port forwarding)

GS
 
It's pretty simple actually. Here's how to do it.

Make sure JFFS is enabled on the Administration->System page. Using Putty, open a shell (telnet/ssh) to the router and copy/paste the following script into the terminal window (right-click will paste). It will automatically create the following up-down.sh script in /jffs. Of course, adjust the firewall rules (ip and ports) according to your own needs.

Code:
cat << "EOF" > /jffs/up-down.sh
#!/bin/sh
set -x # comment/uncomment to disable/enable debugging mode
(
up() {
    iptables -I FORWARD -i $dev -p tcp -d 192.168.1.100 --dport 1000 -j ACCEPT
    iptables -I FORWARD -i $dev -p udp -d 192.168.1.100 --dport 1001 -j ACCEPT
    iptables -I FORWARD -i $dev -p tcp -d 192.168.1.100 --dport 1002 -j ACCEPT
    iptables -t nat -I PREROUTING -i $dev -p tcp --dport 1000 -j DNAT --to-destination 192.168.1.100
    iptables -t nat -I PREROUTING -i $dev -p udp --dport 1001 -j DNAT --to-destination 192.168.1.100
    iptables -t nat -I PREROUTING -i $dev -p tcp --dport 1002 -j DNAT --to-destination 192.168.1.100
}

down() {
    iptables -D FORWARD -i $dev -p tcp -d 192.168.1.100 --dport 1000 -j ACCEPT
    iptables -D FORWARD -i $dev -p udp -d 192.168.1.100 --dport 1001 -j ACCEPT
    iptables -D FORWARD -i $dev -p tcp -d 192.168.1.100 --dport 1002 -j ACCEPT
    iptables -t nat -D PREROUTING -i $dev -p tcp --dport 1000 -j DNAT --to-destination 192.168.1.100
    iptables -t nat -D PREROUTING -i $dev -p udp --dport 1001 -j DNAT --to-destination 192.168.1.100
    iptables -t nat -D PREROUTING -i $dev -p tcp --dport 1002 -j DNAT --to-destination 192.168.1.100
}

[ "$script_type" == "up" ] && up || down

exit 0
) 2>&1 | logger -t $(basename $0)[$$]
EOF
chmod +x /jffs/up-down.sh

Now add the following to the OpenVPN Client Custom Config field.

Code:
script-security 2
up /jffs/up-down.sh
down /jffs/up-down.sh

When the OpenVPN client comes up, it will trigger the up event, call the script in /jffs, and execute the up function (which adds the firewall rules). Similarly, when the OpenVPN client comes down, it will trigger the down event, call the script in /jffs again, and execute the down function (which removes the firewall rules).

Since those rules use the $dev variable (which is set by OpenVPN at runtime), you can run the same script, unchanged, w/ any OpenVPN client merely by adding the same directives to the Custom Config field of that OpenVPN client.

Note, the script enables debugging mode (set -x) by default, and writes all its output to the syslog. This makes it much easier to debug, since you can see the actions of the script (and any errors generated) every time it's executed. And once you get it working, you can disable debugging mode.
 
It's pretty simple actually. Here's how to do it.

Make sure JFFS is enabled on the Administration->System page. Using Putty, open a shell (telnet/ssh) to the router and copy/paste the following script into the terminal window (right-click will paste). It will automatically create the following up-down.sh script in /jffs. Of course, adjust the firewall rules (ip and ports) according to your own needs.

Code:
cat << "EOF" > /jffs/up-down.sh
#!/bin/sh
set -x # comment/uncomment to disable/enable debugging mode
(
up() {
    iptables -I FORWARD -i $dev -p tcp -d 192.168.1.100 --dport 1000 -j ACCEPT
    iptables -I FORWARD -i $dev -p udp -d 192.168.1.100 --dport 1001 -j ACCEPT
    iptables -I FORWARD -i $dev -p tcp -d 192.168.1.100 --dport 1002 -j ACCEPT
    iptables -t nat -I PREROUTING -i $dev -p tcp --dport 1000 -j DNAT --to-destination 192.168.1.100
    iptables -t nat -I PREROUTING -i $dev -p udp --dport 1001 -j DNAT --to-destination 192.168.1.100
    iptables -t nat -I PREROUTING -i $dev -p tcp --dport 1002 -j DNAT --to-destination 192.168.1.100
}

down() {
    iptables -D FORWARD -i $dev -p tcp -d 192.168.1.100 --dport 1000 -j ACCEPT
    iptables -D FORWARD -i $dev -p udp -d 192.168.1.100 --dport 1001 -j ACCEPT
    iptables -D FORWARD -i $dev -p tcp -d 192.168.1.100 --dport 1002 -j ACCEPT
    iptables -t nat -D PREROUTING -i $dev -p tcp --dport 1000 -j DNAT --to-destination 192.168.1.100
    iptables -t nat -D PREROUTING -i $dev -p udp --dport 1001 -j DNAT --to-destination 192.168.1.100
    iptables -t nat -D PREROUTING -i $dev -p tcp --dport 1002 -j DNAT --to-destination 192.168.1.100
}

[ "$script_type" == "up" ] && up || down

exit 0
) 2>&1 | logger -t $(basename $0)[$$]
EOF
chmod +x /jffs/up-down.sh

Now add the following to the OpenVPN Client Custom Config field.

Code:
script-security 2
up /jffs/up-down.sh
down /jffs/up-down.sh

When the OpenVPN client comes up, it will trigger the up event, call the script in /jffs, and execute the up function (which adds the firewall rules). Similarly, when the OpenVPN client comes down, it will trigger the down event, call the script in /jffs again, and execute the down function (which removes the firewall rules).

Since those rules use the $dev variable (which is set by OpenVPN at runtime), you can run the same script, unchanged, w/ any OpenVPN client merely by adding the same directives to the Custom Config field of that OpenVPN client.

Note, the script enables debugging mode (set -x) by default, and writes all its output to the syslog. This makes it much easier to debug, since you can see the actions of the script (and any errors generated) every time it's executed. And once you get it working, you can disable debugging mode.

Many thanks, I will give it a try in the following days and let you know the outcome. Thanks again for your time & help,
GS
 
If you are only forwarding multiple udp/tcp ports to a single IP, this update to eibgrad up-down.sh script can save time using a shell script loop.


Code:
#!/bin/sh

# Port Forwarding for OpenVPN client

LANIP="192.168.1.113"  # IP of the device to forward to
TCPPORTS="9999 8999 9443 9080 9022"  # List of TCP ports to forward to
UDPPORTS="8999" # List of UDP ports to forward to

set -x # comment/uncomment to disable/enable debugging mode
(
up() {
  for PORT in $TCPPORTS
  do
    iptables -I FORWARD -i $dev -p tcp -d $LANIP --dport $PORT -j ACCEPT
    iptables -t nat -I PREROUTING -i $dev -p tcp --dport $PORT -j DNAT --to-destination $LANIP:$PORT
  done
  for PORT in $UDPPORTS
  do
    iptables -I FORWARD -i $dev -p udp -d $LANIP --dport $PORT -j ACCEPT
    iptables -t nat -I PREROUTING -i $dev -p udp --dport $PORT -j DNAT --to-destination $LANIP:$PORT
  done
}

down() {
  for PORT in $TCPPORTS
  do
    iptables -D FORWARD -i $dev -p tcp -d $LANIP --dport $PORT -j ACCEPT
    iptables -t nat -D PREROUTING -i $dev -p tcp --dport $PORT -j DNAT --to-destination $LANIP:$PORT
  done
  for PORT in $UDPPORTS
  do
    iptables -D FORWARD -i $dev -p udp -d $LANIP --dport $PORT -j ACCEPT
    iptables -t nat -D PREROUTING -i $dev -p udp --dport $PORT -j DNAT --to-destination $LANIP:$PORT
  done
}

[ "$script_type" == "up" ] && up || down

exit 0
) 2>&1 | logger -t $(basename $0)[$$]
 
Just for the fun of it, try the following (this is what I do all the time when building these kinds of scripts).

Open a shell to the router, expand the terminal window about two-thirds of the way to the right, move the terminal to the top of the screen, and copy/paste the following command.

Code:
tail -f /tmp/syslog.log

Now open another shell, expand the terminal window about two-thirds of the way to the right, move the terminal to the bottom of the screen (so it doesn't obscure the other terminal window), and copy/paste the following command.

Code:
watch "iptables -t nat -vnL PREROUTING; echo; iptables -vnL FORWARD"

These two shells will allow you to monitor both the syslog and firewall in realtime. If you start and stop the OpenVPN client in the GUI, you'll see the script dumping to the syslog, and the firewall changing in response to both events.

Just a cool technique that makes script development a little easier.
 
If you are only forwarding multiple udp/tcp ports to a single IP, this update to eibgrad up-down.sh script can save time using a shell script loop.


Code:
#!/bin/sh

# Port Forwarding for OpenVPN client

LANIP="192.168.1.113"  # IP of the device to forward to
TCPPORTS="9999 8999 9443 9080 9022"  # List of TCP ports to forward to
UDPPORTS="8999" # List of UDP ports to forward to

set -x # comment/uncomment to disable/enable debugging mode
(
up() {
  for PORT in $TCPPORTS
  do
    iptables -I FORWARD -i $dev -p tcp -d $LANIP --dport $PORT -j ACCEPT
    iptables -t nat -I PREROUTING -i $dev -p tcp --dport $PORT -j DNAT --to-destination $LANIP:$PORT
  done
  for PORT in $UDPPORTS
  do
    iptables -I FORWARD -i $dev -p udp -d $LANIP --dport $PORT -j ACCEPT
    iptables -t nat -I PREROUTING -i $dev -p udp --dport $PORT -j DNAT --to-destination $LANIP:$PORT
  done
}

down() {
  for PORT in $TCPPORTS
  do
    iptables -D FORWARD -i $dev -p tcp -d $LANIP --dport $PORT -j ACCEPT
    iptables -t nat -D PREROUTING -i $dev -p tcp --dport $PORT -j DNAT --to-destination $LANIP:$PORT
  done
  for PORT in $UDPPORTS
  do
    iptables -D FORWARD -i $dev -p udp -d $LANIP --dport $PORT -j ACCEPT
    iptables -t nat -D PREROUTING -i $dev -p udp --dport $PORT -j DNAT --to-destination $LANIP:$PORT
  done
}

[ "$script_type" == "up" ] && up || down

exit 0
) 2>&1 | logger -t $(basename $0)[$$]
FYI, you don't need a loop if the variable contains a CSV... i.e. you can simply add a single iptables rule using the
Code:
-m multiport $TCPPORTS
syntax.

Furthermore, for most situations, you really should not override the OpenVPN 'up/down' scripts provided by the firmware (see '/usr/sbin/updown.sh') unless you fully understand the implications.

Instead, I suggest you use (as per the Wiki) a RMerlin Wiki openvpn-event trigger script and @john9527 kindly provided the openvpn-event script template so you can explicitly choose which openvpn-event trigger script is executed by the specific Server/Client.

e.g. create custom scripts vpnclientX-route-up/vpnclientX-down without the need to add any directives in the VPN Client Custom GUI panel.
 
FYI, you don't need a loop if the variable contains a CSV... i.e. you can simply add a single iptables rule using the
Code:
-m multiport $TCPPORTS
syntax.

Furthermore, for most situations, you really should not override the OpenVPN 'up/down' scripts provided by the firmware (see '/usr/sbin/updown.sh') unless you fully understand the implications.

Instead, I suggest you use (as per the Wiki) a RMerlin Wiki openvpn-event trigger script and @john9527 kindly provided the openvpn-event script template so you can explicitly choose which openvpn-event trigger script is executed by the specific Server/Client.

e.g. create custom scripts vpnclientX-route-up/vpnclientX-down without the need to add any directives in the VPN Client Custom GUI panel.

Thanks for the feedback. To be honest, I'm far less familiar w/ Merlin's implementation of OpenVPN than dd-wrt and tomato (although Merlin being a variant of tomato, I see many similarities). But the one big difference Merlin offers (for good or bad) is the addition of his own event driven model.

In principle, I get where you're coming from. It's considered the default, a standard if you will, for this environment. So I get it, and appreciate it.

After having examined more closely the inner workings of this firmware, it seems to me the openvpn-event script template from @john9527 is almost a necessity, if only to eliminate the confusion of having to handle all your events, for all OpenVPN clients and servers, in one script. Not unless you intend to only support one of the OpenVPN clients or servers. So I wish the existence of that script was more well known. Seems it should be right up there w/ the Merlin documentation regarding use of the openvpn-event script.

I examined the OpenVPN config file for the client, and the only event directives I found were the following:

Code:
route-up vpnrouting.sh
route-pre-down vpnrouting.sh

I noticed these are *always* present, even if the user has configured the OpenVPN client to NOT using policy based routing (e.g., Redirect Internet traffic = All). And I see why. That's the script that calls the openvpn-event script in /jffs.

Code:
PARAM="$dev $tun_mtu $link_mtu $ifconfig_local $ifconfig_remote"
...
run_custom_script(){
        if [ -f /jffs/scripts/openvpn-event ]
        then
                /usr/bin/logger -t "custom_script" "Running /jffs/scripts/openvpn-event (args: $PARAM)"
                /bin/sh /jffs/scripts/openvpn-event $PARAM
        fi
}
...

Wondering where the /usr/sbin/updown.sh fits into all this (to which I could find no reference in the OpenVPN client), I decided to configure the OpenVPN server, and voila, there it was in the server's config file.

Code:
up updown.sh
down updown.sh

So in fact, adding your own up/down directives via the Custom Config field of the OpenVPN *client* doesn't actually present an issue. It will work fine. (I know, I know, that's still not something we'd like to recommend, but I mention it just so everyone is clear about how it actually works).

Of course, the /usr/sbin/updown.sh script similarly calls the openvpn-event in /jffs, but for the OpenVPN server.

My concern with the Merlin approach is two-fold. First, it forces all user-defined OpenVPN event handling to necessarily be driven through the route-up and route-pre-down events. But what if I *want* to handle something via the up/down events of the OpenVPN client? Or numerous other events as well.

Code:
(from the OpenVPN documentation)
--up
    Executed after TCP/UDP socket bind and TUN/TAP open.
--tls-verify
    Executed when we have a still untrusted remote peer.
--ipchange
    Executed after connection authentication, or remote IP address change.
--client-connect
    Executed in --mode server mode immediately after client authentication.
--route-up
    Executed after connection authentication, either immediately after, or some number of seconds after as defined by the --route-delay option.
--route-pre-down
    Executed right before the routes are removed.
--client-disconnect
    Executed in --mode server mode on client instance shutdown.
--down
    Executed after TCP/UDP and TUN/TAP close.
--learn-address
    Executed in --mode server mode whenever an IPv4 address/route or MAC address is added to OpenVPN's internal routing table.
--auth-user-pass-verify
    Executed in --mode server mode on new client connections, when the client is still untrusted.

Granted, by far the most common events are route-up/route-pre-down, followed by up/down. But there are other events, and I don't see how these can be handled correctly via the Merlin openvpn-event, since the timing will be incorrect.

A secondary problem is that the Merlin openvpn-event only passes the command line arguments and environment variables from the route-up/route-pre-down events for the OpenVPN client, and up/down events of the OpenVPN server. But (and I'm not sure everyone is even aware of this) the environment variables provide *much* more information than the command line arguments to the OpenVPN event handler, and they are NOT necessarily the same variables from event to event! IOW, OpenVPN doesn't provide all possible variables to all possible events. It discriminates and limits those variables according to what the OpenVPN developers have deemed appropriate/relevant to the current event. So if every event I wish to handle has to be driven through the openvpn-event script, and that only executes in response to the route-up/route-pre-down or up/down scripts, that's a problem (or at least a limitation).

Now granted, I only skimmed these files/scripts to get a quick overview of how this all works. So I could easily be wrong about some things, or missed something. But assuming for the moment I'm right, it's clear to me that driving everything through those limited events is not going to work in all situations. An OpenVPN script developer who directly uses the OpenVPN event model is NOT going to have these problems. And needs to be aware of the limitations of having all OpenVPN events driven through a single Merlin openvpn-event script that only operates in response to a very limited number of OpenVPN events.

All that said, at least for this particular OP's needs, it doesn't really matter whether they use the Merlin or OpenVPN event driven model. Both will work just fine. But if you chose to use the former, you will need to change the event checking from up/down to route-up/route-pre-down.

Code:
...
route-up() {
...
}

route-pre-down() {
...
}
...
[ "$script_type" == "route-up" ] && route-up
[ "$script_type" == "route-pre-down" ] && route-pre-down
...

Sorry for the length of this post, but I'm just trying to understand the "Merlin way", so to speak. And it is different from other third-party firmware in this respect.

Btw, this thread is probably better suited to the VPN forum.
 
Last edited:
My concern with the Merlin approach is two-fold.
First, it forces all user-defined OpenVPN event handling to necessarily be driven through the route-up and route-pre-down events.
No it doesn't
But what if I *want* to handle something via the up/down events of the OpenVPN client?
@john9527's openvpn-event script works for me...
e.g. see the '--up/--down' script execution triggers...and while I have never created a custom script for the '--route-pre-down' trigger, my verbose version of @john9527's openvpn-script conveniently logs this to the console as an informational message in an attempt to ensure that potential typos when naming the trigger scripts can be detected.
Code:
Apr 22 17:43:13 RT-AC68U openvpn-event[22646]:      Script executing.. for VPN event: vpnclient1-up

Apr 22 17:43:17 RT-AC68U openvpn-routing: Configuring policy rules for client 1
Apr 22 17:43:18 RT-AC68U custom_script: Running /jffs/scripts/openvpn-event (args: tun11 1500 1553 xxx.xxx.xxx.xxx )

Apr 22 17:43:18 RT-AC68U openvpn-event[22953]:      Script executing.. for VPN event: vpnclient1-route-up
Apr 26 03:52:33 RT-AC68U openvpn-routing: Configuring policy rules for client 1
Apr 26 03:52:33 RT-AC68U custom_script: Running /jffs/scripts/openvpn-event (args: tun11 1500 1553 xxx.xxx.xxx.xxx 255.255.255.0 init)

Apr 26 03:52:33 RT-AC68U openvpn-event[2175]:      Script not defined for VPN event: vpnclient1-route-pre-down
Apr 26 03:52:35 RT-AC68U custom_script: Running /jffs/scripts/openvpn-event (args: tun11 1500 1553 xxx.xxx.xxx.xxx 255.255.255.0 init)

Apr 26 03:52:36 RT-AC68U openvpn-event[2249]:      Script executing.. for VPN event: vpnclient1-down
The only time I explicitly specify custom scripts for additional OpenVPN triggers in the GUI, is for for the OpenVPN Server instances, which, as they don't exist in the firmware is a necessity.
Code:
--client-connect /jffs/scripts/VPNClientConnect.sh
--client-disconnect /jffs/scripts/VPNClientDisconnect.sh
but I also allow non-standard psuedo OpenVPN directives
e.g.
Code:
staticip
local wanX
allowperiod
blockperiod
wol
passthru
blockip
etc.
which are neither part of the official OpenVPN command set, nor part of RMerlin's firmware but still conveniently enhance the ease of use of my OpenVPN environment, so I too don't have to strictly adhere to the 'official' OpenVPN configuration directives
Wondering where the /usr/sbin/updown.sh fits into all this (to which I could find no reference in the OpenVPN client)
Here is a snippet of my VPN Client 1 config
/etc/openvpn/client1/config.openvpn
Code:
<snip>
route-noexec
script-security 2
route-delay 2
route-up vpnrouting.sh
route-pre-down vpnrouting.sh
verb 3
up updown.sh
down updown.sh
...
and clearly there are valid (required) references to the '/usr/sbin/updown.sh' script as dictated by the GUI options, so given this is the RMerlin forum, my point about recklessly/needlessly overriding the up/down OpenVPN events still holds true.
So I could easily be wrong about some things, or missed something.
Agreed
But assuming for the moment I'm right, it's clear to me that driving everything through those limited events is not going to work in all situations.
I doubt any firmware feature set is ever perfect and a one-size-satisfies-all feature set is impossible to maintain.

In my opinion, kudos to @RMerlin's design decision - it may not address every esoteric OpenVPN scenario (he consciously strives to avoid unneccesary esoteric feature-bloat), but more than adequately provides a solidly robust solution for 99% of OpenVPN environments, whilst still allowing full flexibility for advanced OpenVPN service management/scenarios.
 
@Martineau

I don't believe you understood the point I was making.

As configured, my OpenVPN client does NOT have either the up or down directives in the OpenVPN config file. I assume there is something different about our respective configurations that accounts for that difference.

I decided to modify the OpenVPN script I recommended for the OP so that it operates w/ openvpn-event.

Code:
cat << "EOF" > /jffs/scripts/openvpn-event
#!/bin/sh
set -x # comment/uncomment to disable/enable debugging mode
(
up() {
    iptables -I FORWARD -i $dev -p tcp -d 192.168.1.100 --dport 1000 -j ACCEPT
    iptables -I FORWARD -i $dev -p udp -d 192.168.1.100 --dport 1001 -j ACCEPT
    iptables -I FORWARD -i $dev -p tcp -d 192.168.1.100 --dport 1002 -j ACCEPT
    iptables -t nat -I PREROUTING -i $dev -p tcp --dport 1000 -j DNAT --to-destination 192.168.1.100
    iptables -t nat -I PREROUTING -i $dev -p udp --dport 1001 -j DNAT --to-destination 192.168.1.100
    iptables -t nat -I PREROUTING -i $dev -p tcp --dport 1002 -j DNAT --to-destination 192.168.1.100
}

down() {
    iptables -D FORWARD -i $dev -p tcp -d 192.168.1.100 --dport 1000 -j ACCEPT
    iptables -D FORWARD -i $dev -p udp -d 192.168.1.100 --dport 1001 -j ACCEPT
    iptables -D FORWARD -i $dev -p tcp -d 192.168.1.100 --dport 1002 -j ACCEPT
    iptables -t nat -D PREROUTING -i $dev -p tcp --dport 1000 -j DNAT --to-destination 192.168.1.100
    iptables -t nat -D PREROUTING -i $dev -p udp --dport 1001 -j DNAT --to-destination 192.168.1.100
    iptables -t nat -D PREROUTING -i $dev -p tcp --dport 1002 -j DNAT --to-destination 192.168.1.100
}

[ "$script_type" == "up" ] && up
[ "$script_type" == "down" ] && down

exit 0
) 2>&1 | logger -t $(basename $0)[$$]
EOF
chmod +x /jffs/scripts/openvpn-event

It writes to the syslog, and here's what it reports when the OpenVPN client is turned ON.

Code:
Apr 28 14:22:30 custom_script: Running /jffs/scripts/openvpn-event (args: tun11 1500 1542 10.13.0.22 10.13.0.21)
Apr 28 14:22:30 openvpn-event[25999]: + [ route-up == up ]
Apr 28 14:22:30 openvpn-event[25999]: + [ route-up == down ]
Apr 28 14:22:30 openvpn-event[25999]: + exit 0

Those last three (3) lines are from my script's execution. The $script_type variable is set to "route-up", NOT "up". No firewall rules got added since the event type didn't match.

When I turn OFF the OpenVPN client, I get the following in the syslog.

Code:
Apr 28 15:31:53 custom_script: Running /jffs/scripts/openvpn-event (args: tun11 1500 1542 10.13.0.66 10.13.0.65 init)
Apr 28 15:31:53 openvpn-event[3559]: + [ route-pre-down == up ]
Apr 28 15:31:53 openvpn-event[3559]: + [ route-pre-down == down ]
Apr 28 15:31:53 openvpn-event[3559]: + exit 0

No firewall rules got deleted because once again the event type didn't match.

As written, this script does NOT work. And the reason is because the up and down directives were never added to *my* OpenVPN configuration file by Merlin, for whatever reasons. That's what I meant when I said "it forces all user-defined OpenVPN event handling to necessarily be driven through the route-up and route-pre-down events."

But then you explained that at least in some OpenVPN client configurations, the up/down directives *are* present. So first problem; the presence of the up/down directives is NOT consistent. And worse, it's not obvious what triggers those directives into being added or removed.

As I stated previously, at least in my example, the script only works if I'm forced to use the route-up and route-pre-down events. And that was my point. Merlin's openvpn-event methodology only works to the extent that he happens to register (via OpenVPN directives) the same OpenVPN events that you're interested in. And as far as I can tell, the only events he ever uses are up/down and route-up/route-pre-down, and NOT consistently. What if I want to do my own PBR (policy based routing) on the OpenVPN server? At least w/ my current OpenVPN server configuration, Merlin doesn't specify the route-up/route-pre-down directives on the server side. So how am I (or some less informed networking newb) supposed to know when I should/can use openvpn-event vs. specifying these events directly in Custom Config? It certainly isn't going to work for the more obscure events, like client-connect, client-disconnect, etc. Are all these idiosyncrasies documented somewhere?

@john9527's script doesn't change any of this one iota. He gets passed the exact same information as my script, based on the same OpenVPN events. As you aptly described it, it's a management script. It's a convenience. It determines which OpenVPN client or server is being triggered, the specific event, and calls your script based on a naming convention. Both his script and mine (as written and based on my current OpenVPN client configuration) are only going to be triggered by the OpenVPN route-up and route-pre-down events.

And btw, please don't be offended simply because someone challenges or questions assumptions. I'm not trying to disparage Merlin. I'm simply asking questions and reporting how I see things. All I'm interested in is understanding how things really work, and making things work better. I agree the Merlin firmware is superb. It beats something like dd-wrt by a mile, and is a serious challenger to other tomato variants (e.g., FreshTomato). But I don't play favorites either. I challenge ALL firmware (just look at the dd-wrt bug reports and you'll find my reporting of issue after issue, same w/ tomato). ALL firmware is worthy of healthy, good faith, criticism. Ppl need to stop taking offense just because someone challenges the accepted norms. A forensic examination of the firmware is good for every developer. Most developers are NOT OpenVPN experts, and so they don't appreciate the finer details of how it operates and why certain assumptions may be wrong, and have negative consequences. Just like you warned me about my assumptions, the same holds true for you and Merlin.
 

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