Port forwarding through OpenVPN
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.
Related videos on Youtube
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, 2022Comments
-
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 about 12 yearsI 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 about 12 yearsYou 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 about 12 yearsOpenVPN is already routing to my LAN. I'm using
push route 192.168.1.0 255.255.255.0
on myserver.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 about 12 yearsTCP connection refused. I can't telnet either. On the REMOTE-SERVER end nothing happens, no packet arrives.
-
El Barto about 12 yearsIf 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 about 12 yearsYou don't need to connect to
192.168.1.10:3306
, you need to connect to10.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 about 12 yearsI added this route on LOCAL-CLIENT:
ip route add 10.8.0.0/24 via 192.168.1.10 dev eth0
. But when I dotelnet 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 about 12 yearsAfter 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