4

I have a service running on localhost which listens port localhost:10000

What I want to do is to forward all traffic coming to publicip:15000 to localhost:10000 where changing the configuration of service is not available.

Service only listens localhost, however traffic comes from outside.

Service runs on linux by the way.

Edit; I tried to add NAT rule like this but I could not be successful.

To configure NAT I did;

iptables --flush
iptables --table nat --flush
iptables --delete-chain
iptables --table nat --delete-chain
iptables --table nat --append POSTROUTING --out-interface lo -j MASQUERADE
iptables -A FORWARD -i eth0 -o lo -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i lo -o eth0 -j ACCEPT
echo 1 > /proc/sys/net/ipv4/ip_forward
service ufw restart

And to start routing execute this;

iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 15000 -j DNAT --to 127.0.0.1:10000

What do you think I am missing ?

Thanks in advance

Baris

1
  • And what type of application is listening on localhost:10000?
    – ALex_hha
    Feb 9, 2014 at 14:32

1 Answer 1

2

It seems that DNAT for loopback traffic is not possible.

Loopback traffic skip both PREROUTING and OUTPUT chains.

RFC 5735 (page 3) says that network 127.0.0.0/8 could not be routed outside of the host itself :

127.0.0.0/8 - This block is assigned for use as the Internet host loopback address. A datagram sent by a higher-level protocol to an address anywhere within this block loops back inside the host. This is ordinarily implemented using only 127.0.0.1/32 for loopback. As described in [RFC1122], Section 3.2.1.3, addresses within the entire 127.0.0.0/8 block do not legitimately appear on any network anywhere.


Also, traffic to loopback interface are considered as Martian Packets :

these packets cannot actually originate as claimed, or be delivered


Workaround :

A simple alternative is to use an inted server on Server side, and its redirect feature.

This way, you can define un service within inetd and set the port where this service will listen to. Then, set the redirect directive to bind this port to 127.0.0.1:port.

In my sample below i will use xinetd (on Ubuntu 12.04 LTS) to bind a mysql server running on 127.0.0.1:10000 :

Step 1 : Install the package : apt-get install xinetd

Step 2 : Edit de the config file /etc/xinetd.conf

Add a service definition similar to the one below :

service my_redirector
{
 type = UNLISTED
 disable = no
 socket_type = stream
 protocol = tcp
 user = root
 wait = no
 port = 15000
 redirect = 127.0.0.1 10000
 log_type = FILE /tmp/somefile.log
}

Step 3 : Restart xinetd daemon : service xinetd restart

Step 4 : let's check for the listener on port 15000 :

# netstat -anp | grep 15000
tcp     0      0 0.0.0.0:15000      0.0.0.0:*     LISTEN      4654/xinetd

Step 5 : Add your iptables rules :

iptables -A INPUT -i eth0 -p tcp -d 192.168.0.60 --dport 15000 -j ACCEPT
iptables -A OUTPUT -o eth0 -p tcp -s 192.168.0.60 --sport 15000 -j ACCEPT

Let's test it :

For testing i have setup mysql to listen on 127.0.0.1:10000. I will try to access it through the xinetd service on port 15000.

First, on Server side, i make sure that mysql server is only listening on 127.0.0.1:10000 :

# netstat -anp | grep :10000
tcp    0    0 127.0.0.1:10000    0.0.0.0:*      LISTEN      4247/mysqld

Then, on Client side, let's check if we can connect using port 15000 :

# telnet 192.168.0.60 15000
Trying 192.168.0.60...
Connected to 192.168.0.60.
Escape character is '^]'.
_
5.5.35-0ubuntu0.12.04.2-logD46S}<P`.6cr4ITIQ<wcmysql_native_password

Seems we can ! :)

Let's try to connect to mysql server :

# mysql -h 192.168.0.60 --port=15000 -u root -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 67
Server version: 5.5.35-0ubuntu0.12.04.2-log (Ubuntu)

Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

Done !

1
  • Thank you user :) That was what I did yesterday but as you have given the same working answer I marked as correct :) Thank you very much :) Feb 10, 2014 at 9:00

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .