a port forwarding situation that iptables seems unable tohandle.

Filip Sneppe filip.sneppe@yucom.be
Thu, 10 Jan 2002 17:04:32 +0100


(posted from a non-subscribed email address, can't send mail from my other
account
at the moment)

Hi Joseph,

Essentially, the problem you are experiencing is one of asymetric routing
and
connection tracking: in your current setup, a packet goes from client PC to
firewall, from firewall to router on same network, over a link to partner's
network.
Reply packets come from over the link, and go from the router on your LAN to
the client PC. Your firewall will not see the reply packets coming from your
partner's network.

Any firewall doing connection tracking will have trouble with this setup.
Since
the NAT framework in iptables is built on top of connection tracking, it
breaks
in this setup.

But there is no reason to dispair. I think it's possible to solve your
problem
with a little creativity. The trick is to make the router (to your partner's
network) on your LAN believe it is getting packets from your firewall, not
from the various clients on the LAN.

Can you try the following:

# Turn off sending icmp redirects
for f in /proc/sys/net/ipv4/conf/*/send_redirects; do
    echo 0 > $f
done

# Redirect port 16 to port 23 on other host
iptables -t nat -A PREROUTING -i eth1 -p tcp -d 192.168.0.6 --dport 16 -j
DNAT --to 10.0.11.18:23

# conntracking
iptables -A FORWARD -m state --state ESTABLISHED, RELATED -j ACCEPT

# simple firewall rule
iptables -A FORWARD -i eth1 -o eth1 -p tcp -d 10.0.11.18 --dport 16 -j
ACCEPT

# make the DNAT'ted stuff appear to come from firewall
iptables -t nat -A POSTROUTING -o eth1 -p tcp -d 10.0.11.18 --dport 16 -j
MASQUERADE


The biggest difference with what you are doing is that, from your partner's
box point of view, all connections will appear to be coming from one and the
same IP address: 192.168.0.6.

Regards,
Filip


-----Original Message-----
From: Joseph Erlewein [mailto:jerlewein@mhc.net]
Sent: Thu 1/10/2002 15:40
To: netfilter@lists.samba.org; teastep@shorewall.net
Cc:
Subject: a port forwarding situation that iptables seems unable tohandle.


A poorly-versed documentary.

Well, I've spent a few weeks on this now, and after meticulously reviewing
goals a day ago,
I've come to the conclusion that what I'm trying to do cannot be done with
the current
availabilities within iptables. While this is the case, I'm not
disappointed, because it was
interesting to learn iptables anyway for firewalling purposes, I'm pretty
good at it now, and
it's stable and easy to understand for that purpose. It also seems to be
able to fulfill the
requirements of small LAN-to-internet type forward/masq situations.

Here, however, is a situation which I can't see a way to resolve with
iptables.

Goal:

Our Linux box sits with one interface on a LAN and one interface to an ISP.T
 his box acts as an organization-wide proxy server. It's running squid for
web proxy and
another couple programs for RealAudio proxy RTSP and SOCKS (only because my
directors told me to install it, BTW. I don't like SOCKS.).

There is a private link on the LAN to a third party vendor site, which our
client PCs (more than 1200)
need to be able to Telnet into. For reasons of security, we decided to ONLY
allow the proxy server
a route down this private path. Not each individual client. This can't be
changed.

This proxy server needs to be able to accept Telnet connections to port 16
on its local interface and
forward them to the third party vendor host on its Telnet port 23. Then the
return packets also need to
make it back to the client, and the session can be established and used.
This needs to work with many
clients simultaneously.


Initial steps:

My first few attempts were miserable failures - due to two facts. 1) I had
no previous experience with
iptables. 2) I did not fully understand the level of routing which would be
necessary for this exchange goal
to be possible.

After some time, and the help of people on this list, especially Tom Eastep
**thank you!!** I was able
to use the following definitions to gain some success:
INTERNALIP internal ip = 192.168.190.6
INERNALIF internal interface = eth1
TESTIPT test input port = 16
TESTOPT test output port 23
TESTIP = 10.0.11.18

$IPT -t nat -A PREROUTING -j DNAT -i $INTERNALIF -p tcp -d
$INTERNALIP --dport $TESTIPT --to $TESTIP:$TESTOPT
$IPT -A FORWARD -j ACCEPT -i $INTERNALIF -o $INTERNALIF -p tcp -d
$TESTIP --dport $TESTOPT
$IPT -A FORWARD -j ACCEPT -i $INTERNALIF -o $INTERNALIF -p tcp -s
$TESTIP --sport $TESTOPT
$IPT -t nat -A POSTROUTING -j SNAT -o $INTERNALIF -p tcp -d $TESTIP --dport
$TESTOPT --to $INTERNALIP:$TESTOPT

With these rules, the following behavior was observed:
telnetting to the target box worked normally and wonderfully.
A client telnetting to port 16 of my proxy server resulted in a connection
to the test box.
The session worked fine.
After disconnecting, there would be a delay (up to 7 minutes) before I could
Telnet to the box again.
Removal of the POSTROUTING rule and reinsertion would eliminate the delay.I
  assume this is due to the fact that the client outgoing port would change
dynamically between sessions. I did not consider this until later.
Also observed: I added a second test definition. It worked similarly. It did
not seem to matter what the client address was, or whether there were two
clients or one client with a session to both, but one single session to each
test definition would work - but no more than one session to each target at
a time. Attempts for more than one session resulted in failures. When a
session would end, the delay was still present before another connect would
be possible. Even though there could only be one session to each target,
both targets can be contacted through the proxy - one session each -
simultaneously.
Also observed: if I were to begin a Telnet to port 16, it would connect.
There is a slight (less than 2 seconds) delay between establishing the
connection and getting a login: prompt. If I ( ^]  then q ) broke the
connection, I could re-Telnet and there would be no ~7 minute delay. If I
let it get to the login: prompt before breaking the connection, there would
be a ~7 minute delay until I could reconnect. At first I suspected my test
box having some security in place, but testing from clients directly did not
produce this result, and it happened when I changed the test box to three
separate systems, one of which being a wireless bridge by Proxim which
accepts Telnet connections. The delay seemed due to settings on the proxy
server and related to my iptables setup.
At first I suspected it was either due to the presence of
RELATED,ESTABLISHED in the FORWARD entries, but I experimented with both
ways with minimal results.


Rethinking the last few weeks' experiments:

Well, last night, I sat down with a big white board and a terminal.
I drew packets.
CLIENT:1951 -> 192.168.190.6:16
ok. I need to change this to the target host before routing.
iptables -t nat -A PREROUTING -j DNAT -i eth1 -p tcp -d
192.168.190.6 --dport 16 --to 10.0.11.18:23
Now I had
CLIENT:1951 -> 10.0.11.18:23
iptables -A FORWARD -j ACCEPT -i eth1 -o eth1 -p tcp -d 10.0.11.18 --dport
23
now it's forwarded.
I need to change the source before it goes out to appear to be from the
proxy server:
iptables -t nat -A POSTROUTING -j SNAT -o eth1 -p tcp -d 10.0.11.18 --dport
23 --to 192.168.190.6
notice how this differs from my previous block which failed - I don't want
to change the source port from 1951, I figure, since multiple clients will
be using all kinds of variable outgoing port numbers, and 1951 is just an
example of one which might at some point be used as a client's outgoing
Telnet session port.
At this point, I realized that packets coming back from the host in response
would be in this format;
10.0.11.18:23 -> 192.168.190.6:1951
This presents a problem. How am I to instruct iptables to "look for a packet
from 10.0.11.18 that is destined for my server at some port which a client
is using to connect to the server on? I thought about something including
ESTABLISHED,RELATED here, but every rule I could come up with didn't seem to
do the trick. I'd need to assign a variable based on the incoming initial
packet - CLIENT:1951 -> 192.168.190.6. If I could store CLIENT:1951 as 2
variables, I'd be set, and could use them to compare incoming packets from
$TESTIP. But... iptables commands affect the kernel routing, and obviously
I'm working in a shell script here which runs once, and does not continually
parse and thus is not a good place to take in and use variables - duh. In
fact, I don't think it's possible to use iptables to create variables to be
used in other rules - it's a basic kernel level function, right? I know
other programs that can run under the kernel that can create variables, temp
files, and reference those for what needs to be done... but something this
basic I would suspect could not do this. Someone tell me if I'm wrong in
that assumption....
So right there I scrapped the attempt, and looked into the FAQ, HOWTO,
tutorial, and man page after much more beer.
REDIRECTION and MASQUERADING caught my eye.

iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 16 -j
REDIRECT --to-port 23
This didn't help me much - the only option for redirect is --to-ports, which
does not help me redirect something coming from 10.0.11.18:23 to my proxy
server 192.168.190.6:variableport.

So what about -j MASQ?
hmm. The man page says the same thing about that - only one
option, --to-ports, is available.
What I really needed was a -j MASQ statement like:
iptables -t nat -A POSTROUTING -o eth1 -j MASQ --from-ports 23.

oh, if only there were a --from-ports option for anything


Conclusion:

So, At this point, having to get up again in less than an hour, I put this
all in a folder and explored alternatives.

looks like aproxy.pl, delegate, tproxy, portfwd, proxy, simpleproxy,
tcpgate, tcpproxy, tcpxd, tinyproxy are all worth having a look at. I was
just hoping to move away from third-party, sketchy, weird, and
buggy/insecure methods - which is why I chose looking into iptables as more
than just a firewall. I still maintain my respect for iptables but at the
same time recognize its limitations and inability to meet the needs of my
goals. I guess it's time to start downloading tarballz, compiling,
debugging, compiling, debugging. debugging, giving up, and moving to the
next candidate once again. Gosh, I love that sequence. :)

I've got the means to develop a GREAT firewall here with iptables, but it
seems it won't do what I need it to do after all.
If I'm missing something here, and someone can point it out, I'll buy you
some Guinness. anyone tried those new rocket-nitrogen-bottles yet? :)


-jre




Joseph R. Erlewein
Information Center Specialist
Munson Healthcare
jerlewein@mhc.net