I have what is essentially a routing problem, and I'm not familiar enough with routing and iptables to effectively troubleshoot and set up my network needs.

What's working

I have an openVPN network set up and working; clients can connect to a LAN through the internet.

What I'd like to have happen

...when a clients connects to the VPN on a given subnet.

  • The client should be accessible from the VPN network

Bonus Points if the rules can do one or more of the following:

  • the client should not be able to initiate connections to the VPN
  • the client should show up in our DNS


Our network topology looks something like this:

   ______        ____________________
 /        \     /                    \
| internet |---| client ( |
 \________/     \____________________/
 /        \
| gateway  |
-----LAN------ (
|    |   |   |
             L_____VPN Server `VPN1` (fictional name/subnet)

Current Settings

Our gateway has the following route defined:  LAN & WLAN

On VPN1, iptables has the following rules

# Flush the filter and nat tables
iptables -t filter -F
iptables -t nat -F

iptables -A INPUT -i tun+ -j ACCEPT
iptables -A FORWARD -i tun+ -j ACCEPT

iptables -A INPUT -i eth0 -j ACCEPT -d
iptables -A FORWARD -i eth0 -j ACCEPT
iptables -t nat -A POSTROUTING -s -d -o tun+ -j MASQUERADE

What is currently happening

Running the command mtr (the connected client's IP on the VPN) shows that the current route is bouncing back and forth between VPN1 and the gateway.

  • iptables -t nat -A POSTROUTING -s -d -o tun+ -j MASQUERADE - Are you sure this rule is correct? The -o option defines the outgoing interface of the packet. But as far as I can tell there is no way this rule would match anything. It sure seems like that should probably be eth0. – Zoredache Dec 19 '13 at 18:14
  • I don't grasp iptables very well, so I'm not 100% sure what any given rule does. If that rule doesn't match anything, then there is a more fundamental problem, no? If no traffic can make it to the tun adapter, how is it ever going to get onto the VPN? How can I route traffic destined for to the tun device/VPN? – jobu1324 Dec 19 '13 at 18:31
  • This is a case where using the long form options might make things clearer. iptables -t nat -A POSTROUTING --source --destination --out-interface tun+ -j MASQUERADE So if I understand your network correctly, is the vpn, is your main network, and this rule is on the VPN server. Why would the outgoing interface be tun+ if the packet is destined for – Zoredache Dec 19 '13 at 18:40
  • I will make the networks clearer in the question, because you have them reversed. is the IP of the VPN server on the LAN, not the VPN. The connecting client is on – jobu1324 Dec 19 '13 at 18:51
  • I've gone through a lot of research on iptables since posting this question, and I discovered my rules are probably misleading; the INPUT and FORWARD chains are mutually exclusive, and the example is only concerned with the FORWARD chains. Correct me if I'm wrong. – jobu1324 Dec 20 '13 at 1:48

After another grueling round of iptables online learning madness, I discovered the solution.

First, however, there is an invalid assumption regarding iptables. My initial approach to the rules was that when a packet was received, it would run through the INPUT and OUTPUT chains. Not so; the minute a rule matches a packet, it leaves the table. Since the filter table is assumed unless specified (e.g. "-t nat"), most of the rules listed are run on the filter table.

Regarding Chains

  • INPUT : run on packets destined for the server
  • OUTPUT : run on packets originating from the server
  • FORWARD : everything else - if a rule matches here, and the "jump" (I like to think if -j as "job" ;) is ACCEPT, the packet will be routed appropriately

A breakdown of the rules

This is a description of the rules under Current Settings above

iptables -t filter -F
iptables -t nat -F

These rules simply flush the filter and nat tables. Note that there are more tables and a more thorough way of clearing iptables rules.

iptables -A INPUT -i tun+ -j ACCEPT

This rule does nothing, because:

  • it is run on traffic destined for VPN1, not another network
  • there is no policy set for incoming traffic, so it is allowed by default

moving on...

iptables -A FORWARD -i tun+ -j ACCEPT

This rule allows traffic coming from to be routed. Rules in the nat table run on packets that match this rule.

iptables -A INPUT -i eth0 -j ACCEPT -d

This rule also has no effect on the desired routing, since traffic is not destined for the VPN1 server.

iptables -A FORWARD -i eth0 -j ACCEPT

This rule allows traffic from to be routed.

iptables -t nat -A POSTROUTING -s -d -o tun+ -j MASQUERADE

This rule causes the traffic destined for the VPN from to look like it came from VPN1, effectively causing VPN1 to look like a gateway.

What's wrong?

The rules should be "OK" as is to get traffic from one network to the next. There isn't any real protection in place - e.g. a default "DROP" policy, etc, but that isn't the point of the question.

If iptables is set up so that it can route the traffic over the VPN, what would cause it to be sent back over eth0 to the gateway? If VPN1 did not know about If the VPN server wasn't aware of that network, it would be treated as internet traffic and sent back to the gateway.

The fix

The solution was to tell the VPN server about the network (this is an openvpn server). There are two ways to do this; if the server is only serving one network, it is a simple configuration setting:


In my case, I had the server route set up, and I needed it to know about an additional network. The configuration looked more like this:


That's it! Once VPN1 had a route to the network, the FORWARD chain is able to route the traffic.

A better iptables setup

After flushing iptables, a better config would look something like this:

# Forward established traffic so that (in the above case) VPN1 doesn't
# drop responses from the client, A.K.A. "the magic"
iptables -t filter -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT

iptables -t filter -A FORWARD     -s -d  -j ACCEPT
iptables -t nat    -A POSTROUTING -s -d  -j MASQUERADE

# Drop everything else that wants to be forwarded
iptables -P FORWARD DROP

Notice that there are no explicit rules for traffic coming from, which means that by default the traffic won't reach the network - except for traffic in response to traffic sent from Now that iptables is set up, clients can be assigned an IP in the VPN config, and added to DNS for a complete solution.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.