[SOLVED] Iptables: how to redirect locally-generated packets to a remote server?
Linux - NetworkingThis forum is for any issue related to networks or networking.
Routing, network cards, OSI, etc. Anything is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Iptables: how to redirect locally-generated packets to a remote server?
I'm trying to workaround a limitation in a server application. The limitation is that I can only connect to a LOCAL mysql database. I am trying to fool the server in to using a remote mysql database. I was hoping to do this by simply forwarding 3306 to another server on the same subnet.
To that end I've set up iptables rules to forward all connections to port 3306 to a non-standard mysql port on a remote server. This works, except that I need to deal with the loopback interface in a special way and I'm stuck.
Since locally-generated packets will never hit the PREROUTING rule, you'll need to setup a near identical rule using OUTPUT to make it work. Here is what I've tried:
Code:
iptables -t nat -A OUTPUT -p tcp -o lo --dport 3306 -j DNAT --to 128.XXX.XXX.XXX:3197
With all of these rules in place, I can connect to another server and n telnet to 3306 on this server and this results in a response from mysql on the remote server. BUT from this server I cannot 'telnet localhost 3306' and get a mysql connection. When I try that, the telnet connection hangs open with no response.
Since locally-generated packets will never hit the PREROUTING rule, you'll need to setup a near identical rule using OUTPUT to make it work. Here is what I've tried:
Code:
iptables -t nat -A OUTPUT -p tcp -o lo --dport 3306 -j DNAT --to 128.XXX.XXX.XXX:3197
I doubt that local packages traverse the -t nat table. Try the command without the -t option.
Or to just be sure where things are growing dim use something like this.
Looking at http://tinyurl.com/yhqr5no I believe that the problem is that once I do the DNAT in -t nat, the packet will not traverse the FORWARD chain. So I think what needs to be done is to resend the packet back to this host so that it originates from eth0 and gets processed by those rules. I tried:
Code:
iptables -t nat -A OUTPUT -p tcp -o lo --dport 3306 -j DNAT --to 169.xxx.xxx.xxx:3306
iptables -t nat -A OUTPUT -p tcp -o lo --dport 3306 -j DNAT --to 128.XXX.XXX.XXX:3197
With all of these rules in place, I can connect to another server and n telnet to 3306 on this server and this results in a response from mysql on the remote server. BUT from this server I cannot 'telnet localhost 3306' and get a mysql connection. When I try that, the telnet connection hangs open with no response.
Thanks for any help!
Can you please, explain, what do you mean by: "BUT from this server I cannot 'telnet localhost 3306' and get a mysql connection"
You can easily telnet to different port and then in iptables use REDIRECT to turn packets to localhost ANY port.
[bwood@dev-10-cms ~]$ telnet 169.xxx.xxx.xxx 3306
Trying 169.xxx.xxx.xxx...
Connected to adm-10-cms.example.com (169.xxx.xxx.xxx).
Escape character is '^]'.
8
5.0.67-log��VR{4/1EG,�!u:^K=/ph;.qr^]
telnet> quit
Connection closed.
[bwood@dev-10-cms ~]$
As you can see I get a response from the remote mysql server when I initiate the connection from dev-10-cms, but I do not when I initiate the connection from adm-10-cms. I need to be able to initate the connection from adm-10-cms.
(Mysql is not running on adm-10-cms. I am definitley getting a response from the 128.xxx box mentioned above.)
If fails when you telnet to localhost port 3306, right?
I'd _guess_ it's because you do a DNAT but probably the source IP address that's set on those packets is still set to 127.0.0.1, isn't that right?
Try snatting or masquerading all traffic to the real mysql server so that it sees your IP address on that network interface, otherwise the mysql server will get 127.0.0.1 as the source address of those packets and won't be able to reply back.
If fails when you telnet to localhost port 3306, right?
I'd _guess_ it's because you do a DNAT but probably the source IP address that's set on those packets is still set to 127.0.0.1, isn't that right?
Try snatting or masquerading all traffic to the real mysql server so that it sees your IP address on that network interface, otherwise the mysql server will get 127.0.0.1 as the source address of those packets and won't be able to reply back.
I guess I could try that as a test. In reality I only want mysql connections to go to the real mysql server. Http and other connections should still come to adm-10-cms.
wait, wait, you confuse me.
nat -A OUTPUT - is located BEFORE router. So, you need to do things different way.
You need to connect to port 3306 on local and remote host - no problems.
But you need separate connections. In that case you can choose port 3306 for local and 4444 for remote server.
Now your iptables rules should be next:
iptables -t nat -A OUTPUT -p tcp -o lo --dport 4444 -j DNAT --to 169.xxx.xxx.xxx:3306
Now packets to port 3306 will not match any rules and go to local host as it suppose to be.
But packets to 4444 will match our rule and NAT will change destination.
Sure... just add filters to the rule in -t nat POSTROUTING that will match only traffic you care to masquerade/snat.
And just to make sure: it fails when you try to connect to telnet localhost 3306 (which is supposed to end up connecting to a remote mysql server), is that right?
But I'm seeing in your rules that you are masquerading all traffic that's going out... so the problem is not what I'm describing. Let me read it again to see what's going on.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.