I had alread started writing this when Antoine put up his reply, so I
though I might as well finish. By the way Antoine,
iptables --table nat --append PREROUTING --protocol tcp \
--destination-port 80 -j DNAT --to-destination 192.168.0.10:80
causes *any* destination port 80 to be routed to my internal webserver,
so I can't access any external websites. Adding a -d <external address>
(which is a line I already have in my iptables init script) fixes that,
but then my original problem isn't fixed.
jack wrote:
> Artom wrote:
>
>> I have a small home LAN with all internal machines - including the
>> webserver this post is about - SNATed to the single (dynamic) IP
>> address my ISP gives me. Note that my NAT router and my server are
>> different machines. I'm using the TLPD IP-Masq HOWTO's stronger
>> iptables ruleset, with some small PORTFW modifications for a file
>> sharing app and the aforementionned webserver.
>>
>> I can access my webserver internally on the 192.168.0.0 network, and
>> people outside can access it using my public IP address (thanks
>> dynamic DNS!), but I can't access it from the inside using my public
>> IP address, i.e. I can't go out and then back in again. I can ping my
>> public IP address from the inside, and I can ssh to it from the inside
>> too, but port 80 connections time out.
>>
>> This isn't a real problem, but out of curiosity, what would be the
>> solution?
>
>
> Think again.
>
> I've seen this problem, accompanied by the answers, around for a while
> by now.
True. It's in the very same HOWTO I used to configure iptables, but the
solution they give does not work for me.
> May I ask You a personal favour (only because I am too lazy to do it
> myself):
>
> Please make a picture of how a connection between an inside web browser
> request to Your public IP would look like. From the beginning over all
> MASQ'ing and everything to Your server and back. And step-by-step.
Here it goes:
This is the setup:
|--------------------|
| internal webserver |--|
|--------------------| | internal interface & address|------------|
|---------------------------------| NAT router |
|-----------------| | |------------|
| internal client |-----| external interface $ address|
|-----------------| |
|
World
The internal client looks at the destination address and its own address
and netmask, realizes that the address is not on the internal network,
and sends it to the NAT router.
Thanks to port 80 PORTFWing:
iptables -A PREROUTING -t nat -p tcp -d <external address> --dport 80 \
-j DNAT --to <webserver>:80
the packet's destination is modified to the webserver's address before
it is routed, and it ends up going out the router's internal interface
unmasqed. The problem is, the stronger ruleset that the TLPD
IP-Masq-HOWTO provides does not allow packets to be incoming and
outgoing on the same interface:
iptables -A FORWARD -i <external interface> -o <internal interface> \
-p tcp --dport 80 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
(allows port 80 PORTFWing)
and
iptables -A FORWARD -i <external interface> -o <internal interface> \
-m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -i <internal interface> -o <external interface> \
-j ACCEPT
(the last two rules before a routed packet is dropped).
Thus any packet from an internal client to the router's external address
on port 80 is dropped by the router.
If
iptables -A FORWARD -i <internal interface> -o <internal interface> \
-p tcp --dport 80 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
is added, then the router no longer drops the packets (check the syslog
to convince yourself), but the webserver still cannot be accessed by an
internal client through the router's external address.
Recall that the packet's source IP is not masqed by the router because
they never make it to the external interface, so when the webserver
sends packets back, it send them directly to the client's address on the
internal network, using the webserver's address on the internal network
as source address. But the client is expecting to hear back from the
router's external address, because that's where it sent the packets, so
it doesn't pick up the packets sent to it by the webserver.
So along with the aforementionned
iptables -A FORWARD -i <internal interface> -o <internal interface> \
-p tcp --dport 80 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
we need to source NAT anything from the internal network going to the
webserver on port 80 to the router's internal address with a
iptables -I POSTROUTING -t nat -p tcp -s <internal network> -d \
<webserver> --dport 80 -j SNAT --to <router>
This is still not enough however, because the very first thing we added
to the iptables init script was
iptables -A FORWARD -i <internal interface> -o <internal interface> \
-p tcp --dport 80 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
and that only allows packets to be incoming and outgoing on the internal
interface if they are destined to port 80. But the client's port is not
80, and so we need to replace that with a
iptables -A FORWARD -i <internal interface> -o <internal interface> -j\
ACCEPT
right before the last
$IPTABLES -A FORWARD -j drop-and-log-it
catch-all rule.
> Make it look cute, and You'll be the author of the "Local-MASQ-HowTo",
> which will be read worldwide.
Cute enough?

>
> Sorry for being brute, Jack.
Hey, no problem. Thanks for the hint. I'll put a modified version of
this post on that webserver some time soon, look for it at coth.no-ip.org.
enjoy!
Artom