IPTABLES - Portforwarding

Scripts with setup, destroy, and modify routing tables and firewall rulesets for client connections.

Moderators: TinCanTech, TinCanTech, TinCanTech, TinCanTech, TinCanTech, TinCanTech

User avatar
Bebop
Forum Team
Posts: 301
Joined: Wed Dec 15, 2010 9:24 pm

IPTABLES - Portforwarding

Post by Bebop » Tue Mar 22, 2011 8:41 pm

Goal: You want incoming connections from the WAN/Internet to be forwarded to the clients in your VPN.

Prerequisites: This example assumes that you already have installed OpenVPN server/client and generated certificates or keys . This example also assumes that you have a basic IPTABLES firewall in place such as the one at: Board index » Scripting and Customizations » Routing and Firewall Scripts » IPTABLES secure Internet tunnel.

Overview: First we'll modify server.conf, then we'll create client connect and disconnect script.

Server.conf insert:

Code: Select all

client-connect /etc/openvpn/clientconnect.sh
client-disconnect /etc/openvpn/clientdisconnect.sh
script-security 2
Create file /etc/openvpn/clientconnect.sh, chmod it to 755, and in it place:

Code: Select all

#!/bin/bash
PORT = 12000
iptables -A FORWARD -p tcp -i eth0 -d $ifconfig_pool_remote_ip --dport $PORT -j ACCEPT
iptables -t nat -A PREROUTING -p tcp -d $ifconfig_local --dport $PORT -j DNAT --to-destination $ifconfig_pool_remote_ip:$PORT
Create file /etc/openvpn/clientdisconnect.sh, chmod it to 755, and in it place:

Code: Select all

#!/bin/bash
PORT=12000
iptables -D FORWARD -p tcp -i eth0 -d $ifconfig_pool_remote_ip --dport $PORT -j ACCEPT
iptables -t nat -D PREROUTING -p tcp -d $ifconfig_local --dport $PORT -j DNAT --to-destination $ifconfig_pool_remote_ip:$PORT
Restart OpenVPN.

Notes: You can only forward a port such as "12000 tcp" to a single client at any one time. You will need to get creative with your port management when you have multiple clients. A simple line such as "PORT 12000" wont be sufficient for a setup with many clients who need ports forwarded. A suggestion would be to look at using a database or flat-file with client/port allocations.

Thanks colin for the memo to add "#!/bin/bash", very important line.

Further notes from the OpenVPN man page:
ifconfig_local
The local VPN endpoint IP address specified in the --ifconfig option (first parameter). Set prior to OpenVPN calling the ifconfig or netsh (windows version of ifconfig) commands which normally occurs prior to --up script execution.

ifconfig_pool_remote_ip
The remote virtual IP address for the TUN/TAP tunnel taken from an --ifconfig-push directive if specified, or otherwise from the ifconfig pool (controlled by the --ifconfig-pool config file directive). This option is set on the server prior to execution of the --client-connect and --client-disconnect scripts.
The cure for boredom is curiosity

colindix
OpenVpn Newbie
Posts: 5
Joined: Sun Sep 18, 2011 8:27 am

Re: IPTABLES - Portforwarding

Post by colindix » Sun Sep 18, 2011 8:44 am

Hi,

I've tried several different combinations of this and I can't seem to get it to work. I have read the linked article ('secure internet tunnel') and believe i was running all relevant lines during the tests.

I know it seems obvious, but if you can elaborate on what you are placing in $ifconfig_pool_remote_ip and $ifconfig_local that would be appreciated. I'm testing on an EC2 instance and have tried both the tunnel IPs (10.8.0.x) and the instance's local IP (other 10.x.x.x).

To test I just set up a netcat listener on a port on the client machine and was connecting to the server from a 3rd machine to the same port. At best, all my tests gave me timeouts and when I added logging to IPtables it didn't show anything further than a SYN (all default policies were ACCEPT so I don't believe the returns were being firewalled).

I'm kind of stumped on where to go from here, so any advice would be appreciated.

Thanks

User avatar
Bebop
Forum Team
Posts: 301
Joined: Wed Dec 15, 2010 9:24 pm

Re: IPTABLES - Portforwarding

Post by Bebop » Sun Sep 18, 2011 2:43 pm

Except for $PORT, the other variables are environment variables set automatically by OpenVPN. I shall update the OP to make that more clear.

So in practice what it means is that $ifconfig_pool_remote_ip and $ifconfig_local are set automatically by OpenVPN and you do not need to set them manually.

More info: http://openvpn.net/index.php/open-sourc ... npage.html
Scroll down do section "Environmental variables"

If this does not solve your issue, let me know.
The cure for boredom is curiosity

colindix
OpenVpn Newbie
Posts: 5
Joined: Sun Sep 18, 2011 8:27 am

Re: IPTABLES - Portforwarding

Post by colindix » Sun Sep 18, 2011 6:06 pm

Thanks for the reply, though I'm now a bit embarrased by the question :oops:

Unfortunately those variables aren't exposed to the shell so I couldn't use them from the command line while tinkering... which forced me to set it up again using a CA as I had previously been using the simpler static key setup for testing. I did, however finally resolve my issue and as always it's one of those simple (and subsequently embarrassing) things you don't think about. Suffice to say the port forwarding is now working and I am greatly indebted for your original post.

I do have one more question though.

While attempting to implement the automated scripts per your first post, I am constantly getting the message:
client-connect command failed: could not execute external program
I've tried everything I can think of - including moving the scripts to /tmp and re-verifying permissions etc but I still receive the message. My config does drop permissions prior to the client-connect, however I would have thought that moving the files to temp (as a diagnostic tool, not a permanent solution) would solve that problem. Is the permission-drop feature incompatible with external scripts?

Thanks again

Colin

User avatar
Bebop
Forum Team
Posts: 301
Joined: Wed Dec 15, 2010 9:24 pm

Re: IPTABLES - Portforwarding

Post by Bebop » Sun Sep 18, 2011 8:57 pm

In server.conf this line is important.. just double check it exists:

Code: Select all

script-security 2
and (if it already exists) maybe change it to:

Code: Select all

script-security 3
Also, use:

Code: Select all

chmod 755 /etc/openvpn/the-script-name.sh
and also chown the script to the same user that OpenVPN runs as. In your case probably 'nobody'. And just to be safe, chmod+chown the folder containing the script too. Whether or not these last steps fix the problem I can't say, but I am sure they cause no harm at the very least.
The cure for boredom is curiosity

colindix
OpenVpn Newbie
Posts: 5
Joined: Sun Sep 18, 2011 8:27 am

Re: IPTABLES - Portforwarding

Post by colindix » Sun Sep 25, 2011 5:02 am

Just thought I'd report back in that unfortunately these suggestions didn't work and I always get the same "could not execute external program" error following the client connect.

I haven't had a chance to look at it for almost a week (been racing against the clock on another ovpn setup) but I tried everything I could think of to no avail. The last thing that has come to mind during the week is a bung character in the script file messing with it. Although this is unlikely to be a problem (no windows computers were used in the chain) I'll give it a shot.

I'll probably end up going with CCD's anyway - hopefully I'll have more luck with that.

I have noticed there to be some general flaky-ness with respect to some of openvpn's configuration stuff. One that I have seen several times is clients not taking the DHCP/DNS parameters passed to them, which has been quite frustrating. While I accept the possibility that there is something in the client OS network config causing the problem and not OVPN (I've been using Centos5.7 on all of these and I am not familiar with the RedHat way of doing things), as far as I can tell the client is just not processing it. Another example of this is the "redirect-gateway" option - I have had no luck with clients acting on it without the same command being present in the client.conf file (which the docs make no mention of requiring).

For future googlers I'll report back if I have any luck with the CCD option when I get around to trying it.

Thanks again for your help.

Colin

bencori
OpenVpn Newbie
Posts: 7
Joined: Tue Nov 08, 2011 7:11 pm

Re: IPTABLES - Portforwarding

Post by bencori » Wed Nov 09, 2011 6:26 pm

Hi. Would this trick work when we force UDP connections ? Thank you.

User avatar
janjust
Forum Team
Posts: 2703
Joined: Fri Aug 20, 2010 2:57 pm
Location: Amsterdam
Contact:

Re: IPTABLES - Portforwarding

Post by janjust » Thu Nov 10, 2011 8:22 am

can you be a bit more specific? the VPN connection can be either UDP or TCP based, it's the forwarding a WAN connection to the client that is discussed here. Forwarding UDP connections using iptables is possible, but it can be tricky , as UDP is stateless: some routesr and applications don't respond well to NAT'ted/forwarded UDP traffic. YMMV.

colindix
OpenVpn Newbie
Posts: 5
Joined: Sun Sep 18, 2011 8:27 am

Re: IPTABLES - Portforwarding

Post by colindix » Thu Nov 10, 2011 8:28 am

bencori wrote:Hi. Would this trick work when we force UDP connections ? Thank you.
I only use proto UDP on my links and it works fine. I'm using it right now to forward certain services to another machine down an openvpn link.

I still haven't had any luck with the client-connect scripts but I haven't tried it in a few weeks now. I expect I'll have some time to do in the next couple of weeks so I'll report back here how I go with the CCDs and trying the client-connect scripts on another OS.

Colin

User avatar
Bebop
Forum Team
Posts: 301
Joined: Wed Dec 15, 2010 9:24 pm

Re: IPTABLES - Portforwarding

Post by Bebop » Sat Nov 19, 2011 9:06 pm

colindix wrote: I still haven't had any luck with the client-connect scripts but I haven't tried it in a few weeks now.
Feel free to post your server.conf. I thought this would be a simple solve.. eg: filename, file permissions.
The cure for boredom is curiosity

colindix
OpenVpn Newbie
Posts: 5
Joined: Sun Sep 18, 2011 8:27 am

Re: IPTABLES - Portforwarding

Post by colindix » Sun Nov 20, 2011 7:57 am

Aha!

I was in the middle of replying to this post (to say still no luck) when I began, again, tinkering with things. After some time I realised a rather silly error, as a result of taking your first post a little too literally.

The problem was that, for some reason, I didn't recognise that the clientconnect script is just a plain shell script, and thus I didn't have the "#!/bin/bash" interpreter line at the top of it. That is the reason it was failing, and ownership/permissions or script-security settings were not at fault. Yeah, I know, pretty dumb :oops:

I did have to make a few other changes though, which I'll record here to possibly save someone else some time. Note, I was testing on CentOS6 so YMMV.

1. The iptables command has some issues with the priv-drop feature. Even though the user/group lines were further down the server.conf file, the order doesn't seem to matter. While it's not a perfect solution from a security perspective, I edited the sudoers file to allow the openvpn user to execute the iptables command without a password. Don't forget to specify the complete path to the command (though this will probably vary depending on OS).

2. The big difference was that, in my setup, the $ipconfig_pool_remote_ip maps to the client tunnel end (in my case 10.8.0.6) and the $ifconfig_local maps to the server tunnel end (10.8.0.1). With the clientconnect script, your line

Code: Select all

iptables -t nat -D PREROUTING -p tcp -d $ifconfig_local --dport $PORT -j DNAT --to-destination $ifconfig_pool_remote_ip:$PORT
caused it to redirect packets incoming on the server's tunnel interface to the client's. What it should be doing is redirecting incoming packets on the public interface to the client's tunnel interface.

To troubleshoot this I put echo commands in the clientconnect script to verify the IPs, which it prints into the openvpn.log file. Note, I am running this on an amazon EC2 machine to test and this NATs the public IP to a local 10.x IP, so that may be messing with the OpenVPN environment variable, making it different to yours.

In my case, to fix it I added a couple of lines to identify the local incoming interface IP and replaced $ifconfig_local with that var.
So my complete clientconnect script is now (I left the echo cmds in to demonstrate):

Code: Select all

#!/bin/bash
PORT=55555
LOCALIP=`/sbin/ifconfig eth0|grep 'inet\ addr'|cut -d":" -f2|cut -d" " -f1`
echo ifconfigpool is $ifconfig_pool_remote_ip
sudo /sbin/iptables -A FORWARD -p tcp -i eth0 -d $ifconfig_pool_remote_ip --dport $PORT -j ACCEPT
echo ifconfiglocal is $ifconfig_local
sudo /sbin/iptables -t nat -A PREROUTING -p tcp -d $LOCALIP --dport $PORT -j DNAT --to-destination $ifconfig_pool_remote_ip:$PORT
There are probably a couple of other ways to achieve this also, but this worked for me.

Thanks again for your help and great original post, I certainly wouldn't have worked this out without it.

Colin

User avatar
Bebop
Forum Team
Posts: 301
Joined: Wed Dec 15, 2010 9:24 pm

Re: IPTABLES - Portforwarding

Post by Bebop » Sun Nov 20, 2011 9:57 am

colindix wrote: I was in the middle of replying to this post (to say still no luck) when I began, again, tinkering with things. After some time I realised a rather silly error, as a result of taking your first post a little too literally.

The problem was that, for some reason, I didn't recognise that the clientconnect script is just a plain shell script, and thus I didn't have the "#!/bin/bash" interpreter line at the top of it. That is the reason it was failing, and ownership/permissions or script-security settings were not at fault. Yeah, I know, pretty dumb :oops:
Damn.. thats well found on your part. Without thinking I chopped the interesting part from my shell script.. I totally should have added in right away, and over time I forgot, and hence, wasn't able to trouble-shoot it proper with you either. I take full credit for this major delay in your new setup.

Anyways thank you also, in this case I've learned some stuff too. When I have the time to tinker with my server I'll see re-evaluate according to your changes.

Congrats on the setup 8-)
The cure for boredom is curiosity

grungo
OpenVpn Newbie
Posts: 1
Joined: Mon Dec 19, 2011 10:25 am

Re: IPTABLES - Portforwarding

Post by grungo » Mon Dec 19, 2011 10:56 am

Thanks for the tutorial. I have been following along and it seems to be working (canyouseeme.org can see me), but I was wondering if you could show me what a healthy "iptables --list" looks like, please. Mine doesn't show ports, which seemed strange to me (a total noob).

People should note that they might need to change the interface name in the scripts supplied if theirs differ (mine did).

elessard84
OpenVpn Newbie
Posts: 7
Joined: Sun Mar 11, 2012 3:31 am

Re: IPTABLES - Portforwarding

Post by elessard84 » Mon Mar 12, 2012 6:24 pm

Your tutorial is almost what i need. What can be the setting to do the same thing but with openvpn directly on the router(tomato firmware)? I'm struggling with my problem for weeks... Because simples port fowarding don't work even if my vpn is bridged with my local network....

edit: corrected some spelling

mkanet
OpenVpn Newbie
Posts: 14
Joined: Thu May 23, 2013 2:15 am

Re: IPTABLES - Portforwarding

Post by mkanet » Thu May 23, 2013 3:01 am

I have OpenVPN running on my router as well (Asus N56U custom firmware). I also want to forward WAN/Internet ports to my VPN client with an openvpn-assigned IP (that always stays the same).

I dont want to start blindly making changes unless I have a good working example that would work with a router-based OpenVPN server. It sounds by your post the stuff in the OP don't work for you when following the instructions exactly.

I'm hoping there are people still watching this thread; and, offer to help.

MKANET
elessard84 wrote:Your tutorial is almost what i need. What can be the setting to do the same thing but with openvpn directly on the router(tomato firmware)? I'm struggling with my problem for weeks... Because simples port fowarding don't work even if my vpn is bridged with my local network....

edit: corrected some spelling

User avatar
janjust
Forum Team
Posts: 2703
Joined: Fri Aug 20, 2010 2:57 pm
Location: Amsterdam
Contact:

Re: IPTABLES - Portforwarding

Post by janjust » Thu May 23, 2013 4:21 pm

the scripts posted were *almost* working; these versions work for me.

clientconnect.sh:

Code: Select all

#!/bin/bash
PUBLIC_IP=XX.XX.XX.XX
PORT=12000
/sbin/iptables -A FORWARD -p tcp -i eth0 -d $ifconfig_pool_remote_ip --dport $PORT -j ACCEPT
/sbin/iptables -t nat -A PREROUTING -p tcp -d $PUBLIC_IP --dport $PORT -j DNAT --to-destination $ifconfig_pool_remote_ip:$PORT
clientdisconnect.sh:

Code: Select all

#!/bin/bash
PUBLIC_IP=XX.XX.XX.XX
PORT=12000
/sbin/iptables -D FORWARD -p tcp -i eth0 -d $ifconfig_pool_remote_ip --dport $PORT -j ACCEPT
/sbin/iptables -t nat -D PREROUTING -p tcp -d $PUBLIC_IP --dport $PORT -j DNAT --to-destination $ifconfig_pool_remote_ip:$PORT
but you also need an iptables rule to masquerade or SNAT traffic:

Code: Select all

#!/bin/bash
/sbin/iptables -t nat -A POSTROUTING -o tun+ -j MASQUERADE
plus,make sure you run the openvpn process as root, as otherwise you will get an error when running iptables.

mkanet
OpenVpn Newbie
Posts: 14
Joined: Thu May 23, 2013 2:15 am

Re: IPTABLES - Portforwarding

Post by mkanet » Thu May 23, 2013 4:38 pm

I really appreciate the quick reply! Would it be too much to ask for you to post the actual code (real example) if I needed to forward incoming tcp ports 80, 8080, 22 to my VPN client with IP: 10.249.84.2?

If it matters, my VPN server's numeric IP changes from time to time. Only the DDNS name is always the same: mydomainname.com

Thanks a million!!

mkanet
OpenVpn Newbie
Posts: 14
Joined: Thu May 23, 2013 2:15 am

Re: IPTABLES - Portforwarding

Post by mkanet » Thu May 23, 2013 5:07 pm

...also, Im not sure which which script I need to put the two lines below. Is it in clientconnect.sh or clientdisconnect.sh?

Code: Select all

#!/bin/bash
/sbin/iptables -t nat -A POSTROUTING -o tun+ -j MASQUERADE

mkanet
OpenVpn Newbie
Posts: 14
Joined: Thu May 23, 2013 2:15 am

Re: IPTABLES - Portforwarding - //A few questions//

Post by mkanet » Sat May 25, 2013 9:02 pm

It's understandable that nobody's motivated enough to help me any further. Honestly, Ive been trying to figure this out for several days now; and, need just a little more help to use the information given to me.

I would be more than happy to discretely donate very generously via Paypal for anyone willing to help me out. I'm guessing it wouldnt take any more than 10-15 minutes of someone's time to answer my questions below.

Please see my questions below:

  • "I was hoping for actual code, (a real example) of what I can add to my OpenVPN server configuration if I need to forward incoming tcp ports 80, 8080, 22 to my VPN client with IP: 10.249.84.2.

    If it matters, my VPN server's public numeric IP changes from time to time. Only the DDNS name is always the same: myddnsdomainname.com"


Also, I saw the below two lines posted; however, it doesn't say which script/config file I need to put this in:

Code: Select all

#!/bin/bash
/sbin/iptables -t nat -A POSTROUTING -o tun+ -j MASQUERADE
Thanks so much in advance,
MKANET

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
janjust wrote:the scripts posted were *almost* working; these versions work for me.

clientconnect.sh:

Code: Select all

#!/bin/bash
PUBLIC_IP=XX.XX.XX.XX
PORT=12000
/sbin/iptables -A FORWARD -p tcp -i eth0 -d $ifconfig_pool_remote_ip --dport $PORT -j ACCEPT
/sbin/iptables -t nat -A PREROUTING -p tcp -d $PUBLIC_IP --dport $PORT -j DNAT --to-destination $ifconfig_pool_remote_ip:$PORT
clientdisconnect.sh:

Code: Select all

#!/bin/bash
PUBLIC_IP=XX.XX.XX.XX
PORT=12000
/sbin/iptables -D FORWARD -p tcp -i eth0 -d $ifconfig_pool_remote_ip --dport $PORT -j ACCEPT
/sbin/iptables -t nat -D PREROUTING -p tcp -d $PUBLIC_IP --dport $PORT -j DNAT --to-destination $ifconfig_pool_remote_ip:$PORT
but you also need an iptables rule to masquerade or SNAT traffic:

Code: Select all

#!/bin/bash
/sbin/iptables -t nat -A POSTROUTING -o tun+ -j MASQUERADE
plus,make sure you run the openvpn process as root, as otherwise you will get an error when running iptables.

mkanet
OpenVpn Newbie
Posts: 14
Joined: Thu May 23, 2013 2:15 am

Re: IPTABLES - Portforwarding

Post by mkanet » Sun May 26, 2013 12:08 am

I made a lot of presumptions; but, not knowing what I'm doing, below is the best I could come up with. It's probably all wrong. I had no idea where the masquerade rule would go, so guessed it would go in my firewall.sh script. I also presumed I could use a DDNS name instead of a static numeric IP. I'm not sure if that would put an extra load on the server doing DNS queries; or, maybe they get cached?

Anyway, hopefully, someone will have a little time to spare to help me out.

server.conf

Code: Select all

client-connect /etc/openvpn/clientconnect.sh
client-disconnect /etc/openvpn/clientdisconnect.sh
script-security 2
clientconnect.sh

Code: Select all

#!/bin/bash
PUBLIC_IP=myddnsdomainname.com

/sbin/iptables -A FORWARD -p tcp -i eth0 -d $ifconfig_pool_remote_ip --dport 80 -j ACCEPT
/sbin/iptables -t nat -A PREROUTING -p tcp -d $PUBLIC_IP --dport 80 -j DNAT --to-destination $ifconfig_pool_remote_ip:80

/sbin/iptables -A FORWARD -p tcp -i eth0 -d $ifconfig_pool_remote_ip --dport 8080 -j ACCEPT
/sbin/iptables -t nat -A PREROUTING -p tcp -d $PUBLIC_IP --dport 8080 -j DNAT --to-destination $ifconfig_pool_remote_ip:8080

/sbin/iptables -A FORWARD -p tcp -i eth0 -d $ifconfig_pool_remote_ip --dport 22 -j ACCEPT
/sbin/iptables -t nat -A PREROUTING -p tcp -d $PUBLIC_IP --dport 22 -j DNAT --to-destination $ifconfig_pool_remote_ip:22
clientdisconnect.sh

Code: Select all

#!/bin/bash
PUBLIC_IP=myddnsdomainname.com

/sbin/iptables -D FORWARD -p tcp -i eth0 -d $ifconfig_pool_remote_ip --dport 80 -j ACCEPT
/sbin/iptables -t nat -D PREROUTING -p tcp -d $PUBLIC_IP --dport 80 -j DNAT --to-destination $ifconfig_pool_remote_ip:80

/sbin/iptables -D FORWARD -p tcp -i eth0 -d $ifconfig_pool_remote_ip --dport 8080 -j ACCEPT
/sbin/iptables -t nat -D PREROUTING -p tcp -d $PUBLIC_IP --dport 8080 -j DNAT --to-destination $ifconfig_pool_remote_ip:8080

/sbin/iptables -D FORWARD -p tcp -i eth0 -d $ifconfig_pool_remote_ip --dport 22 -j ACCEPT
/sbin/iptables -t nat -D PREROUTING -p tcp -d $PUBLIC_IP --dport 22 -j DNAT --to-destination $ifconfig_pool_remote_ip:22
firewall.sh

Code: Select all

/sbin/iptables -t nat -A POSTROUTING -o tun+ -j MASQUERADE

Post Reply