LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Networking
User Name
Password
Linux - Networking This forum is for any issue related to networks or networking.
Routing, network cards, OSI, etc. Anything is fair game.

Notices


Reply
  Search this Thread
Old 03-22-2010, 10:13 PM   #1
briwood
LQ Newbie
 
Registered: Jun 2007
Location: San Francisco, CA
Posts: 15

Rep: Reputation: 0
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.


Code:
iptables -t nat -A PREROUTING -p tcp --dport 3306 -j DNAT --to 128.XXX.XXX.XXX:3197
iptables -A FORWARD -p tcp -d 128.XXX.XXX.XXX --dport 3197 -j ACCEPT
iptables -t nat -A POSTROUTING  -j MASQUERADE
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.

Here are what my chains look like:

Code:
# iptables -L 
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     tcp  --  anywhere             mysql.example.com tcp dpt:embrace-dp-s 

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Chain RH-Firewall-1-INPUT (0 references)
target     prot opt source               destination      

iptables -L -t nat -v
Chain PREROUTING (policy ACCEPT 131 packets, 61868 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    1    60 DNAT       tcp  --  any    any     anywhere             anywhere            tcp dpt:mysql to:128.XXX.XXX.XXX:3197 

Chain POSTROUTING (policy ACCEPT 23 packets, 1470 bytes)
 pkts bytes target     prot opt in     out     source               destination         
  204 13161 MASQUERADE  all  --  any    any     anywhere             anywhere            
Chain OUTPUT (policy ACCEPT 826 packets, 53871 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DNAT       tcp  --  any    lo      anywhere             anywhere            tcp dpt:mysql to:128.XXX.XXX.XXX:3197
Thanks for any help!
 
Old 03-23-2010, 03:55 AM   #2
zhjim
Senior Member
 
Registered: Oct 2004
Distribution: Debian Squeeze x86_64
Posts: 1,748
Blog Entries: 11

Rep: Reputation: 233Reputation: 233Reputation: 233
Quote:
Originally Posted by briwood View Post
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.
Code:
iptables -I OUTPUT -j LOG --log-prefix "Out: " --log-tcp-options
do this for all the chains.
 
Old 03-23-2010, 04:04 AM   #3
win32sux
LQ Guru
 
Registered: Jul 2003
Location: Los Angeles
Distribution: Ubuntu
Posts: 9,870

Rep: Reputation: 380Reputation: 380Reputation: 380Reputation: 380
Quote:
Originally Posted by zhjim View Post
I doubt that local packages traverse the -t nat table.
They do. See chapter 6 of Oskar Andreasson's famous tutorial.

Do an "iptables -nvL -t nat" on your box to see the packet counters with your own eyes.

Last edited by win32sux; 03-23-2010 at 04:05 AM.
 
Old 03-23-2010, 10:17 AM   #4
briwood
LQ Newbie
 
Registered: Jun 2007
Location: San Francisco, CA
Posts: 15

Original Poster
Rep: Reputation: 0
Yes in fact in table 3-2 at http://www.faqs.org/docs/iptables/tr...goftables.html it says:

source of packet = local process
table=nat
chain=output:
Quote:
This chain can be used to NAT outgoing packets from the firewall itself.
Quote:
Originally Posted by win32sux View Post
Do an "iptables -nvL -t nat" on your box to see the packet counters with your own eyes.
Here it is again:
Code:
# iptables -nvL -t nat
Chain PREROUTING (policy ACCEPT 53 packets, 24986 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    1    60 DNAT       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           tcp dpt:3306 to:128.xxx.xxx.xxx:3197 

Chain POSTROUTING (policy ACCEPT 4 packets, 258 bytes)
 pkts bytes target     prot opt in     out     source               destination         
  194 12506 MASQUERADE  all  --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain OUTPUT (policy ACCEPT 197 packets, 12704 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DNAT       tcp  --  *      lo      0.0.0.0/0            0.0.0.0/0           tcp dpt:3306 to:128.xxx.xxx.xxx:3197
That -t nat OUTPUT rule is:

Code:
iptables -t nat -A OUTPUT -p tcp -o lo --dport 3306 -j DNAT --to 128.xxx.xxx.xxx:3197
Without that -t nat OUTPUT rule:
Code:
# telnet localhost 3306
Trying 127.0.0.1...
telnet: connect to address 127.0.0.1: Connection refused
telnet: Unable to connect to remote host: Connection refused
With that -t nat OUTPUT rule:
Code:
[root@adm-10-cms ~]# telnet localhost 3306
Trying 127.0.0.1...

(hangs...^C)

hmm...
 
Old 03-23-2010, 10:47 AM   #5
briwood
LQ Newbie
 
Registered: Jun 2007
Location: San Francisco, CA
Posts: 15

Original Poster
Rep: Reputation: 0
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
(169.xxx is the ip of this machine.)

...but that's not quite it.
 
Old 03-23-2010, 10:56 AM   #6
nimnull22
Senior Member
 
Registered: Jul 2009
Distribution: OpenSuse 11.1, Fedora 14, Ubuntu 12.04/12.10, FreeBSD 9.0
Posts: 1,571

Rep: Reputation: 92
Quote:
Originally Posted by briwood View Post
...

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.

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.
 
Old 03-23-2010, 11:19 AM   #7
briwood
LQ Newbie
 
Registered: Jun 2007
Location: San Francisco, CA
Posts: 15

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by nimnull22 View Post
Can you please, explain, what do you mean by: "BUT from this server I cannot 'telnet localhost 3306' and get a mysql connection"
The server where I'm modifying iptables is adm-10-cms:

Code:
[root@adm-10-cms ~]# telnet localhost 3306
Trying 127.0.0.1...

(hangs...^C)
Connecting from a different server:
Code:
[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.)
 
Old 03-23-2010, 11:20 AM   #8
eantoranz
Senior Member
 
Registered: Apr 2003
Location: Costa Rica
Distribution: Kubuntu, Debian, Knoppix
Posts: 2,092
Blog Entries: 1

Rep: Reputation: 90
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.
 
Old 03-23-2010, 11:30 AM   #9
nimnull22
Senior Member
 
Registered: Jul 2009
Distribution: OpenSuse 11.1, Fedora 14, Ubuntu 12.04/12.10, FreeBSD 9.0
Posts: 1,571

Rep: Reputation: 92
Use REDIRECT rule in iptables to turn local port <ANY> to local port <ANY>.
 
Old 03-23-2010, 11:39 AM   #10
briwood
LQ Newbie
 
Registered: Jun 2007
Location: San Francisco, CA
Posts: 15

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by nimnull22 View Post
Use REDIRECT rule in iptables to turn local port <ANY> to local port <ANY>.
Are you saying to do what I tried in #5:

Code:
iptables -t nat -A OUTPUT -p tcp -o lo --dport 3306 -j DNAT --to 169.xxx.xxx.xxx:3306
but to leave out the "--dport 3306" and remove the ":3306"?
 
Old 03-23-2010, 11:42 AM   #11
briwood
LQ Newbie
 
Registered: Jun 2007
Location: San Francisco, CA
Posts: 15

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by eantoranz View Post
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.
 
Old 03-23-2010, 11:55 AM   #12
nimnull22
Senior Member
 
Registered: Jul 2009
Distribution: OpenSuse 11.1, Fedora 14, Ubuntu 12.04/12.10, FreeBSD 9.0
Posts: 1,571

Rep: Reputation: 92
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.
 
Old 03-23-2010, 12:04 PM   #13
eantoranz
Senior Member
 
Registered: Apr 2003
Location: Costa Rica
Distribution: Kubuntu, Debian, Knoppix
Posts: 2,092
Blog Entries: 1

Rep: Reputation: 90
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?
 
Old 03-23-2010, 12:09 PM   #14
eantoranz
Senior Member
 
Registered: Apr 2003
Location: Costa Rica
Distribution: Kubuntu, Debian, Knoppix
Posts: 2,092
Blog Entries: 1

Rep: Reputation: 90
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.
 
Old 03-23-2010, 12:13 PM   #15
eantoranz
Senior Member
 
Registered: Apr 2003
Location: Costa Rica
Distribution: Kubuntu, Debian, Knoppix
Posts: 2,092
Blog Entries: 1

Rep: Reputation: 90
can you do a tcpdump on your network interface that connects to the nerwork where the remote mysql server is?

something like:
tcpdump -i blah -p tcp and port 3197 -n -v

and then try to do the telnet and see what addresses/ports are showing up?
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
redirect output to remote server via ssh packets Programming 4 05-19-2009 08:30 PM
How to mount remote server locally to a machine? ammar Linux - Networking 1 08-18-2006 01:02 AM
iptables:redirect ports except for packets destined for fierwall(upto 256 ip) itself mmshekiba Linux - Security 1 02-02-2006 12:08 PM
logging to a remote syslog server is dropping packets draeician73 Linux - Security 1 10-20-2004 06:19 PM
iptables- not passing packets to server jbrandis Linux - Security 4 12-09-2001 04:44 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Networking

All times are GMT -5. The time now is 05:45 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration