> OK, I think I have moved forward to some extent. I added this rule before > all other rules: > > $IPTABLES -t nat -p tcp -A PREROUTING -d $EXTIP --dport 80 -j DNAT --to > 192.168.1.2:88 > > Then I added the forwarding rule later in the script: > > $IPTABLES -A FORWARD -d 192.168.1.2 -j ACCEPT This rule is probably a bad idea for security - basically, any traffic that happens to come through the FORWARD chain with a destination of 192.168.1.2 will get sent on. I prefer to put the port spec here too, like this: $IPTABLES -A FORWARD -p tcp -d 192.168.1.2 --dport 88 -j ACCEPT
Note that that's the post-NAT port, not port 80. > This works as expected for traffic coming through the external interface, > i.e. the internet. But when I try to access from my LAN (incidently also the > destination machine for the DNAT rule, i.e. 192.168.1.2) it doesn't work. Where are you trying to access your LAN _from_? Accessing one computer within the LAN from another doesn't even touch the firewall, so that's a seperate issue. If you're trying to get to it from the firewall itself, check your INPUT and OUTPUT rules...data the firewall sends to them goes through OUTPUT, and their replies go through INPUT. Also, the DNAT rules/etc. also get applied to traffic from the LAN in your setup. If that's not the desired behavior, put in a source specifier, like so: $IPTABLES -t nat -A PREROUTING -i $EXTIF -p tcp -d $EXTIP --dport 80 -j DNAT --to 192.168.1.2:88 (where $EXTIF = eth0 or whatever's connected to the Internet) > My understanding is this: > 1) The DNAT prerouting rule changes the destination of the packet so that it > is no longer targetted to the firewall/internet machine. This is correct, and it happens _before_ the packets go through any of the filter rules. > 2) Now that the destination is no longer the firewall machine, the only > rules that apply to the packets are forward rules, since the packet did not > orginate from the firewall machine (otherwise output rules would apply too?) Not entirely correct. Packets are never, ever, ever sent through more than one set of filter rules. These are FORWARD packets. Stuff from the firewall would go through OUTPUT but not FORWARD. Stuff to the firewall goes through INPUT but not FORWARD. Everything else goes through FORWARD, but neither INPUT nor OUTPUT. Also, use connection tracking, and allow ESTABLISHED and RELATED stuff through regardless, so you only have to filter the start of each connection in the rules. > Is this correct? Why isn't the DNAT working from within the LAN? DNAT should work from within the LAN with this setup...ie, opening http://$internalIPofFirewall/ should be forwarded to the server at port 88. If it's not, you might check your SNAT rules...those get applied AFTER all the filtering, so the packet would still be on the FORWARD chain, but you probably want to make sure they don't SNAT traffic internal to the LAN that's just passing through the firewall. Use a -o $EXTIF clause to do that if you haven't. Also, never drop packets from the mangle table - use your filter tables to do packet filtering. So, to overview how things work: 1. Every packet passes through the PREROUTING chains in NAT and MANGLE tables, then one built-in filter chain, out of INPUT, OUTPUT, and FORWARD. Then it goes through POSTROUTING in NAT and MANGLE, and only then is it sent out from the firwall. 2. So, when you write filter rules, write them for packets that have been DNATted, but not yet SNATted (note: netfilter silently does the connection tracking to make SNAT replies in PREROUTING too, so packets coming from the Internet on an SNATted connection show up with their 'real' destinations on the LAN.) 3. Always remember that NAT is based on conntrack - the first packet on each connection has the NAT rules applied, and then every packet after that is handled silently by netfilter - but they're still filtered by the filter table, so you need to allow them there. My method is to permit anything on an established connection and deny all but a few connections from starting, but there are other methods. -EtherMage
