Port forwarding through OpenVPN

25,688

It's because the OUTPUT chain only acts on packets originating from a local process. (See this useful image here.)

If you replace (or supplement if you still want to connect form the gateway) that rule with:

iptables -t nat -A PREROUTING -p tcp --dport 3306 -j DNAT --to 10.8.0.51

And, if you haven't already allowed for the traffic:

iptables -t filter -A FORWARD -p tcp -d 10.8.0.51 --dport 3306 -j ACCEPT

Then your connection should go through. Since it's already working form the gateway, you can be sure MySQL is listening correctly and that its server is accepting the connection.

However, I question whether you actually need NAT at all. Routing alone should handle this, with the appropriate FORWARD rule. That routing can be established manually or through the VPN server config, it depends on your requirements. If you want to look at this option, can you add your openvpn server configuration and the output of route -n to your post?

EDIT

To ensure the connection routes back over the VPN, you'll need a route to your LAN from the server. To add this manually on the MySQL Server:

route add -net 192.168.1.0/24 dev tun0 (if tun0 is your VPN client interface).

If it works, it's better to add this to your VPN client config: route 192.168.1.0/24 (This will automatically create the route on connection, regardless of the tunnel interface or the PPP endpoint addresses being used)

A useful debugging tip: tcpdump -i tun0 -qtln port 3306 on the server will show you the mysql traffic going through the VPN adaptors (client or server). You should be able to see where the connection handshaking is going awry.

Share:
25,688

Related videos on Youtube

El Barto
Author by

El Barto

Web developer & Sysadmin Weapons of choice: Python, PHP, MySQL, GNU/Linux, Apache & Nginx. I also happen to be a history student interesed in Early Modern European history and history of religions.

Updated on September 18, 2022

Comments

  • El Barto
    El Barto over 1 year

    Here's my scenario. I have three hosts.

    1) GATEWAY running OpenVPN Server. It has 1 LAN IP (192.168.1.10) and 1 OpenVPN IP (10.8.0.1).

    2) LOCAL-CLIENT, a machine within the same LAN as GATEWAY, with 1 LAN IP (192.168.1.12)

    3) REMOTE-SERVER, a MySQL server which is a CLIENT of the OpenVPN Server. It has 1 public IP and 1 OpenVPN IP (10.8.0.51).

    I want to be able to connect to MySQL on REMOTE-SERVER from LOCAL-CLIENT through the VPN.

    So far I've enabled IP forwarding and added a port forward like this:

    echo "1" > /proc/sys/net/ipv4/ip_forward
    iptables -t nat -A OUTPUT -p tcp --dport 3306 -j DNAT --to 10.8.0.51
    

    This works from GATEWAY, I can connect to MySQL using 192.168.1.10 as host. But when I try from LOCAL-CLIENT I get a "Connection refused" error (either using MySQL client or telnet to port 3306).

    What am I missing here?

    BTW, I've also tried forwarding HTTP port to test against the Apache which is also running on REMOTE-SERVER and I get the same results, so it's not a MySQL issue.

    More information:

    Kernel IP routing table
    Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
    10.8.0.2        0.0.0.0         255.255.255.255 UH    0      0        0 tun0
    10.8.0.0        10.8.0.2        255.255.255.0   UG    0      0        0 tun0
    192.168.1.0     0.0.0.0         255.255.255.0   U     1      0        0 eth1
    5.5.0.0         0.0.0.0         255.255.252.0   U     0      0        0 as0t0
    5.5.4.0         0.0.0.0         255.255.252.0   U     0      0        0 as0t1
    5.5.8.0         0.0.0.0         255.255.252.0   U     0      0        0 as0t2
    5.5.12.0        0.0.0.0         255.255.252.0   U     0      0        0 as0t3
    0.0.0.0         192.168.1.1     0.0.0.0         UG    0      0        0 eth1
    

    Here's my iptables on GATEWAY (AFAIK, most of the rules are added by OpenVPN server). This is after applying the changes suggested by @SmallClanger.

    iptables -L -n
    Chain INPUT (policy ACCEPT)
    target     prot opt source               destination         
    AS0_ACCEPT  all  --  0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED 
    AS0_ACCEPT  all  --  0.0.0.0/0            0.0.0.0/0           
    AS0_IN_PRE  all  --  0.0.0.0/0            0.0.0.0/0           mark match 0x2000000/0x2000000 
    AS0_ACCEPT  tcp  --  0.0.0.0/0            192.168.1.10        state NEW tcp dpt:915 
    AS0_ACCEPT  tcp  --  0.0.0.0/0            192.168.1.10        state NEW tcp dpt:914 
    AS0_ACCEPT  udp  --  0.0.0.0/0            192.168.1.10        state NEW udp dpt:917 
    AS0_ACCEPT  udp  --  0.0.0.0/0            192.168.1.10        state NEW udp dpt:916 
    AS0_WEBACCEPT  all  --  0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED 
    AS0_WEBACCEPT  tcp  --  0.0.0.0/0            192.168.1.10        state NEW tcp dpt:943 
    
    Chain FORWARD (policy ACCEPT)
    target     prot opt source               destination         
    AS0_ACCEPT  all  --  0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED 
    AS0_IN_PRE  all  --  0.0.0.0/0            0.0.0.0/0           mark match 0x2000000/0x2000000 
    AS0_OUT_S2C  all  --  0.0.0.0/0            0.0.0.0/0           
    ACCEPT     all  --  10.8.0.0/24          0.0.0.0/0           
    REJECT     all  --  0.0.0.0/0            0.0.0.0/0           reject-with icmp-port-unreachable 
    ACCEPT     tcp  --  0.0.0.0/0            10.8.0.51           tcp dpt:3306 
    
    Chain OUTPUT (policy ACCEPT)
    target     prot opt source               destination         
    AS0_OUT_LOCAL  all  --  0.0.0.0/0            0.0.0.0/0           
    
    Chain AS0_ACCEPT (7 references)
    target     prot opt source               destination         
    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           
    
    Chain AS0_DNS (2 references)
    target     prot opt source               destination         
    ACCEPT     all  --  0.0.0.0/0            172.20.2.26         
    DROP       all  --  0.0.0.0/0            0.0.0.0/0           
    
    Chain AS0_IN (4 references)
    target     prot opt source               destination         
    ACCEPT     all  --  0.0.0.0/0            5.5.0.1             
    ACCEPT     all  --  0.0.0.0/0            10.8.0.1            
    ACCEPT     all  --  0.0.0.0/0            192.168.1.0/24      
    AS0_IN_POST  all  --  0.0.0.0/0            0.0.0.0/0           
    
    Chain AS0_IN_POST (1 references)
    target     prot opt source               destination         
    AS0_OUT    all  --  0.0.0.0/0            0.0.0.0/0           
    DROP       all  --  0.0.0.0/0            0.0.0.0/0           
    
    Chain AS0_IN_PRE (2 references)
    target     prot opt source               destination         
    AS0_DNS    tcp  --  0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:53 
    AS0_DNS    udp  --  0.0.0.0/0            0.0.0.0/0           state NEW udp dpt:53 
    AS0_IN     all  --  0.0.0.0/0            5.5.0.0/20          
    AS0_IN     all  --  0.0.0.0/0            192.168.0.0/16      
    AS0_IN     all  --  0.0.0.0/0            172.16.0.0/12       
    AS0_IN     all  --  0.0.0.0/0            10.0.0.0/8          
    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           
    
    Chain AS0_OUT (2 references)
    target     prot opt source               destination         
    DROP       all  --  0.0.0.0/0            0.0.0.0/0           
    
    Chain AS0_OUT_LOCAL (1 references)
    target     prot opt source               destination         
    DROP       icmp --  0.0.0.0/0            0.0.0.0/0           icmp type 5 
    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           
    
    Chain AS0_OUT_S2C (1 references)
    target     prot opt source               destination         
    AS0_OUT    all  --  0.0.0.0/0            0.0.0.0/0           
    
    Chain AS0_WEBACCEPT (2 references)
    target     prot opt source               destination         
    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0 
    

    Here's the NAT table

    iptables -L -n -t nat
    Chain PREROUTING (policy ACCEPT)
    target     prot opt source               destination         
    AS0_NAT_PRE_REL_EST  all  --  0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED 
    AS0_DPFWD_UDP  udp  --  0.0.0.0/0            192.168.1.10        udp dpt:1194 state NEW 
    AS0_DPFWD_TCP  tcp  --  0.0.0.0/0            192.168.1.10        tcp dpt:443 state NEW 
    DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:3306 to:10.8.0.51 
    
    Chain POSTROUTING (policy ACCEPT)
    target     prot opt source               destination         
    AS0_NAT_POST_REL_EST  all  --  0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED 
    AS0_NAT_PRE  all  --  0.0.0.0/0            0.0.0.0/0           mark match 0x2000000/0x2000000 
    MASQUERADE  all  --  10.8.0.0/24          0.0.0.0/0           
    
    Chain OUTPUT (policy ACCEPT)
    target     prot opt source               destination         
    
    Chain AS0_DPFWD_TCP (1 references)
    target     prot opt source               destination         
    DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0           to:192.168.1.10:914 
    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           
    
    Chain AS0_DPFWD_UDP (1 references)
    target     prot opt source               destination         
    DNAT       udp  --  0.0.0.0/0            0.0.0.0/0           to:192.168.1.10:916 
    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           
    
    Chain AS0_NAT (2 references)
    target     prot opt source               destination         
    SNAT       all  --  0.0.0.0/0            0.0.0.0/0           to:192.168.1.10 
    SNAT       all  --  0.0.0.0/0            0.0.0.0/0           to:10.8.0.1 
    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           
    
    Chain AS0_NAT_POST_REL_EST (1 references)
    target     prot opt source               destination         
    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           
    
    Chain AS0_NAT_PRE (1 references)
    target     prot opt source               destination         
    AS0_NAT_TEST  all  --  0.0.0.0/0            5.5.0.0/20          
    AS0_NAT_TEST  all  --  0.0.0.0/0            192.168.0.0/16      
    AS0_NAT_TEST  all  --  0.0.0.0/0            172.16.0.0/12       
    AS0_NAT_TEST  all  --  0.0.0.0/0            10.0.0.0/8          
    AS0_NAT    all  --  0.0.0.0/0            0.0.0.0/0           
    
    Chain AS0_NAT_PRE_REL_EST (1 references)
    target     prot opt source               destination         
    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           
    
    Chain AS0_NAT_TEST (4 references)
    target     prot opt source               destination         
    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           
    ACCEPT     all  --  0.0.0.0/0            5.5.0.0/20          
    AS0_NAT    all  --  0.0.0.0/0            0.0.0.0/0 
    

    Edit:

    Based on @SmallClanger's comments I realized I didn't need to do any port forwarding or NAT. LOCAL-CLIENT is able to connect to REMOTE-SERVER through its VPN's IP. For this, since my VPN Gateway is not the default gateway, I had to add this static route on LOCAL-CLIENT:

    ip route add 10.8.0.0/24 via 192.168.1.10 dev eth0
    

    I also had to delete this FORWARD rule on iptables which was preventing LOCAL-CLIENT to connect to any VPN client:

    REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
    
  • El Barto
    El Barto about 12 years
    I removed my previous rules and added the ones you suggested, but now I can't connect neither from LOCAL-CLIENT nor GATEWAY. I'm updating now my post to include the routing table.
  • SmallClanger
    SmallClanger about 12 years
    You will need the OUTPUT rule you created to connect form the gateway itself. However, you'll also need a route back to your LAN from the MySQL server. I'll edit my answer.
  • El Barto
    El Barto about 12 years
    OpenVPN is already routing to my LAN. I'm using push route 192.168.1.0 255.255.255.0 on my server.conf. I can currently connect from REMOTE-SERVER to LOCAL-CLIENT without problems. But still, when I try to connect from LOCAL-CLIENT to REMOTE-SERVER's MySQL I get connection refused.
  • El Barto
    El Barto about 12 years
    TCP connection refused. I can't telnet either. On the REMOTE-SERVER end nothing happens, no packet arrives.
  • El Barto
    El Barto about 12 years
    If I do a tcpdump on the Gateway, on eth1 (where the LAN IP is) the only thing I get is: IP 192.168.1.12.57541 > 192.168.1.10.3306: tcp 0
  • SmallClanger
    SmallClanger about 12 years
    You don't need to connect to 192.168.1.10:3306, you need to connect to 10.8.0.51:3306 As there's no DNAT rule in place, the gateway is simply saying "I'm not listening on port 3306, go away." If you connect to the REMOTE-SERVER VPN endpoint address directly, it should route through.
  • El Barto
    El Barto about 12 years
    I added this route on LOCAL-CLIENT: ip route add 10.8.0.0/24 via 192.168.1.10 dev eth0. But when I do telnet 10.8.0.51 3306 I still get a connection refused error. And the tcpdump on GATEWAY says: IP 192.168.1.12.44406 > 10.8.0.51.3306: tcp 0.
  • El Barto
    El Barto about 12 years
    After a loooong time struggling, I found the problem was I had this rule on iptables: REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable