Archived

This topic is now archived and is closed to further replies.

Crispy

forwarding

Recommended Posts

I'm having a hard time figuring out how to forward an incoming request on port x to a dynamically (via DHCP) created local IP on port y. The specific case:
          |-> subnet1
out ->[R]-|
          |-> subnet2
R is a Linux router box, which runs a DHCP server for subnets 1 and 2. My first problem is coming up with a proper iptables script to add to the forwarding chain. Is it that I need to add an ACCEPT clause to the INPUT chain and a different clause to the FORWARD chain? And also, given that I'm forwarding a port to a http server, do I also need to add a clause to the OUTPUT chain? Secondly, since the IP is volatile, can I do this based on the MAC address of the computer running the http server? edit: added formatting
[edited by - crispy on January 16, 2004 4:53:42 PM]

Share this post


Link to post
Share on other sites
Assuming that hosts behind the router don''t need to access the server, I think a rule like this would work (where $INET_IP is the external address and $HTTP_IP is the web server''s address):

iptables -t nat -A PREROUTING --dst $INET_IP -p tcp --dport 80 -j DNAT --to-destination $HTTP_IP

I believe, because this is a DNAT rule, you don''t need to mess with any of the other chains. Provided, of course, that the router is configured to allow packets to internal hosts in the first place.

I''m not sure how to handle the DHCP aspect of it though.

Share this post


Link to post
Share on other sites
Thanks for the reply SiCrane, but the DHCP part is what is most confusing for me as well .

edit: realised I said a bunch of nonsense...

Anyway - I think the rule you posted, SiCrane, is quite okay - for the time being I'm bypassing the DHCP problem manually. However, there's a problem I can't understand. Namely, the webserver, when requested from the local host (not localhost) over the external IP, gives a timeout error. Does this mean that the problem is with routing or is it because my webserver is malconfigured (currently etc/hosts includes an entry that defines the local machine by the IP obtained from the DHCP server).

There are no rules in the nat, mangle or filter tables that I could say are conflicting the current rule. However, there's yet another problem: the previous admin set up an alias for the router's IP, which the router recognizes (it substitutes its public IP with it in iptables when a new rule is added) - one, which doesn't seem to be recognized by any DNS (given that he set it up at his own domain, and the fact that the entire router is infested with stuff that concerns me indirectly, but I don't have much clue about since I was handed the computer blindfolded, I don't yet know where the substitution is made). Just to give a hint of the integrity of the system: there is no such thing as an iptables configuration file (if there is, it's somewhere I don't know to look for it at) under sysconfig. Neither is locate present. grep'ing for it hasn't yielded and result so far, plus I have no clue as to what linux distro it is... And this is only one of the things that doesn't add up...







[edited by - Crispy on January 19, 2004 7:47:07 AM]

Share this post


Link to post
Share on other sites
The problem is, that the rule I gave you only works for external IP addresses, which I already mentioned. To get it to work for other machines behind the router you need to add a SNAT rule:

iptables -t nat -A POSTROUTING -p tcp --dst $HTTP_IP --dport 80 -j SNAT --to-source $LAN_IP

In this case $LAN_IP is the IP of the interface on router of the subnet that the http server is on. Be careful: this seriously messes with the logging on http server; it makes it seems as if all url requests come from the router. I don''t know of any way to get around this. (Short of completely restructuring the network.) Then again, I don''t have much experience with server admin, so it''s possible that someone else might know a way.

Also, you might need to add this rule to the router, to make sure that the router itself can access the http server:

iptables -t nat -A OUTPUT --dst $INET_IP -p tcp --dport 80 -j DNAT --to-destination $HTTP_IP

Depending on the services you run, you might be able to get around needing these rules by altering your internal DNS server to point to the local http server for your domain name. I''d look into that, because, as I said, these rules seriously mess with the http server''s logging functions.

Share this post


Link to post
Share on other sites
Aha. Thanks again for the explanation. Here''s a thought I can''t check right now, but what about applying the same rule (from your first post) to the internal interface? Would that work?







Share this post


Link to post
Share on other sites
That first rule is already applied to the internal interfaces. Here''s what happens: Host A, behind the router, sends a packet to $INET_IP. The packet is DNAT''ed by the router, which replaces the destination address, but it''s not SNAT''ed, so the source address remains the same. The http server gets the packet, does whatever processing it needs, and sends a response packet. Because Host A is on a internal subnet, the http server sends it directly to the original source address. However, when the response packet gets to Host A, the source address is the http server, not $INET_IP. Host A gets confused and drops the packet.

The SNAT rule forces the http server to send the packet back to the router instead of directly to Host A, then the router can properly un-NAT the packet and everything works happily. (Except for the fact that logging on the http server becomes hopelessly borked.)

Share this post


Link to post
Share on other sites

hi,

maybe I have misunderstood your question but I assume that your out NIC uses external IPs while you SUB1 and SUB2 uses internal. That does not make any difference anyway if you use external or internal on your SUBs behind the router.

However, if you want to forward requests that comes from outside to your interface standing on the "out" side, you need to accept the forward:

iptables -A FORWARD -p TCP -i $OUTSIDE_IFACE -o $SUB1_IFACE -d $INT_HTTP1_IP --dport 80 -j allowed

-- OR --

iptables -A FORWARD -p TCP -i $OUTSIDE_IFACE -o $SUB2_IFACE -d $INT_HTTP1_IP --dport 80 -j allowed

where $OUTSIDE_IFACE is the NIC (eth0, eth1, etc) that is on the outside and $SUB1_IFACE and $SUB2_IFACE is the NIC connected to subnet 1 or subnet 2.

This tells that forwarding is allowed.

Then you need to preroute the request:

iptables -t nat -A PREROUTING -p TCP -i $OUTSIDE_IFACE -d $HTTP1_IP --dport 80 -j DNAT --to-destination $INT_HTTP1_IP

-- OR --

iptables -t nat -A PREROUTING -p TCP -i $OUTSIDE_IFACE -d $HTTP2_IP --dport 80 -j DNAT --to-destination $INT_HTTP2_IP

where HTTP1_IP/HTTP2_IP is external IP addresses and INT_HTTP1_IP/INT_HTTP2_IP is the IP addresses on the HTTP servers you want to forward the request too (which can be either internal or external).

However, maybe I misunderstood you a bit....

Share this post


Link to post
Share on other sites
Cheers! I never did thank you for the explanation, guys. Anyway - I went a little out of my way to set up all requested servers on the router machine. Even though it''s not up yet so much as would be possible to test it properly, I''m pretty sure that kind of prerouting is no longer neccesary. There''s still a couple of people in the subnets that want to set up their own servers (http and otherwise), but I think they can manage not being able to receive connections from the local network (they can still test the site themselves over localhost).

Thanks again, anyway!





Share this post


Link to post
Share on other sites