[Nottingham] some iptables magic required

Michael perl at tecspy.com
Wed Dec 29 19:55:41 GMT 2004


Hi All,

After a recent change-around with my domains I'm now hosting most of my
websites from my home LAN rather than, as previously, delegate this
simple task to someone else for an inflated charge and get zero service
in return! (Yes, I imagine there's probably plenty of decent hosting
providers out there but I'm quite determined to do this for "free" and
for myself.) It also occurs that the Perl Mongers free web hosting is to
withdraw shell access and, wait for it, withdraw Perl CGI! (ahem... it
took me a while to stop laughing - coffee squirting out of my nostrils -
but it's their decision.) So in the new year I'll be hosting Nottingham
Perl Mongers site from my home LAN too. Everything's going just great so
far: I transferred my domains to a cheap US-based company, set up free
DNS and mail forwarding at ZoneEdit and my sites are working away nicely
on Apache2 and mod_perl.

One problem remains and I'm sure there's a good answer for it: the
machines on my LAN aren't able to establish connections with the web
server when using the proper externally-resolved names due to the
iptables rules or NAT on the firewall/gateway/DNS machine. What is the
magic mantra to add to my script that would point my internal clients
back onto the LAN?

Specifics follow:-

My firewall machine, a trusty Pentium 60, runs Devil-Linux, 2.4.22
kernel, has 2 NICs and runs a hardly-modified version of the standard
Devil-Linux 2-NIC iptables script which follows: -

#!/bin/bash
#
# $Source:
/cvsroot/devil-linux/build/config/etc/init.d/firewall.rules.2nic,v $
# $Revision: 1.8.2.2 $
# $Date: 2003/10/21 13:53:56 $
#
# http://www.devil-linux.org
#
#
# Basic Firewall rules for 2 NIC's and NAT
#

# Path to executables
IPTABLES=/usr/sbin/iptables
MODPROBE=/sbin/modprobe

OUT_DEV=eth0 # Internet
INT_DEV=eth1 # Internal/protected network.

# Stop forwarding while setting up.
echo "0" > /proc/sys/net/ipv4/ip_forward

# Uncomment the following line to enable logging:
# LOGGING="yes"

# Optional Modules:
${MODPROBE} ip_conntrack_ftp
${MODPROBE} ip_nat_ftp
${MODPROBE} ip_conntrack_irc
${MODPROBE} ip_nat_irc
#${MODPROBE} ip_owner

# Only needed if we're going to log.
[ -n "$LOGGING" ] && ${MODPROBE} ipt_LOG

# Flush tables & setup Policy
${IPTABLES} -F  # flush chains
${IPTABLES} -X  # delete user chains
${IPTABLES} -Z # zero counters
for t in `cat /proc/net/ip_tables_names`
do
  ${IPTABLES} -F -t $t
  ${IPTABLES} -X -t $t
  ${IPTABLES} -Z -t $t
done
${IPTABLES} -P INPUT DROP # Policy = DROP
${IPTABLES} -P OUTPUT DROP #  Drop all packets that are
${IPTABLES} -P FORWARD DROP #  not specifically accepted.

# Local interface - do not delete!
${IPTABLES} -A INPUT -i lo -j ACCEPT
${IPTABLES} -A OUTPUT -o lo -j ACCEPT

# We accept anything from the inside.
${IPTABLES} -A INPUT -i ${INT_DEV} -j ACCEPT
${IPTABLES} -A OUTPUT -o ${INT_DEV} -j ACCEPT

# Allow our firewall to connect.
${IPTABLES} -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
${IPTABLES} -A OUTPUT -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT

# Allow Ping and friends.
${IPTABLES} -A INPUT  -p icmp -j ACCEPT
${IPTABLES} -A OUTPUT -p icmp -j ACCEPT

# Fast reject for Ident to eliminate email delays.
${IPTABLES} -A INPUT -p TCP --dport 113 -i ${OUT_DEV} -j REJECT
--reject-with tcp-reset

# Masquerading (aka NAT, PAT, ...)
${IPTABLES} -t nat -A POSTROUTING -o ${OUT_DEV} -j MASQUERADE

# Uncomment/modify the next 4 lines to forward a service to an internal IP.
# SERVER_IP=192.168.1.1 # Internal IP of server.
# PORT=22  # 22 = SSH.  Change to 80 for web server, etc.
# ${IPTABLES} -A PREROUTING -i ${OUT_DEV} -t nat -p TCP --dport $PORT -j
DNAT --to ${SERVER_IP}:${PORT}
# ${IPTABLES} -A FORWARD -p TCP -d ${SERVER_IP} --dport $PORT -i
${OUT_DEV} -o ${INT_DEV} -j ACCEPT

# Block invalid connections from the internet.
[ -n "$LOGGING" ] && \
   ${IPTABLES} -A FORWARD -m state --state NEW,INVALID -i ${OUT_DEV} -j
LOG --log-prefix "FORWARD INVALID: "
${IPTABLES} -A FORWARD -m state --state NEW,INVALID -i ${OUT_DEV} -j DROP

# Allow connections to the internet from the internal network.
${IPTABLES} -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
${IPTABLES} -A FORWARD -m state --state NEW -i ${INT_DEV} -j ACCEPT

# Prevent NetBIOS and Samba from leaking.
${IPTABLES} -t nat -A PREROUTING -p TCP --dport 135 -j DROP
${IPTABLES} -t nat -A PREROUTING -p UDP --dport 135 -j DROP
${IPTABLES} -t nat -A PREROUTING -p TCP --dport 137:139 -j DROP
${IPTABLES} -t nat -A PREROUTING -p UDP --dport 137:139 -j DROP
${IPTABLES} -t nat -A PREROUTING -p TCP --dport 445 -j DROP
${IPTABLES} -t nat -A PREROUTING -p UDP --dport 445 -j DROP

# make interactive sesions a bit more interactive under load
${IPTABLES} -A PREROUTING -t mangle -p TCP --sport ssh -j TOS --set-tos
Minimize-Delay
${IPTABLES} -A PREROUTING -t mangle -p TCP --sport ftp -j TOS --set-tos
Minimize-Delay
${IPTABLES} -A PREROUTING -t mangle -p TCP --sport ftp-data -j TOS
--set-tos Maximize-Throughput

# Log invalid packets from DROP policy:
if [ -n "$LOGGING" ] ; then
     ${IPTABLES} -A INPUT -d 255.255.255.255 -j DROP # do not log broadcasts
     ${IPTABLES} -A INPUT -d 224.0.0.0/8 -j DROP # do not log Microsoft
multicasts
     ${IPTABLES} -A INPUT -m limit --limit 3/minute --limit-burst 3 -j
LOG --log-prefix "INPUT policy: "
     ${IPTABLES} -A OUTPUT -m limit --limit 3/minute --limit-burst 3 -j
LOG --log-prefix "OUTPUT policy: "
     ${IPTABLES} -A FORWARD -m limit --limit 3/minute --limit-burst 3 -j
LOG --log-prefix "FORWARD policy: "
fi

# enable dynamic IP address following
echo 7 > /proc/sys/net/ipv4/ip_dynaddr

# stop some smurf attacks.
echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts

# Don't accept source routed packets.
echo "0" > /proc/sys/net/ipv4/conf/all/accept_source_route

# Syncookies
echo "1" > /proc/sys/net/ipv4/tcp_syncookies

# Stop IP spoofing,
for interface in /proc/sys/net/ipv4/conf/*/rp_filter; do
  echo "1" > $interface
done

# Stop ICMP redirect
for interface in /proc/sys/net/ipv4/conf/*/accept_redirects; do
  echo "0" > ${interface}
done

# Enable bad error message protection.
echo "1" > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses

# Enabling IP forwarding.
echo "1" > /proc/sys/net/ipv4/ip_forward
#--------------- >8 END OF SCRIPT - CUT HERE >8 -------------------#

OK, my version is the same as this but with a few ports forwarded and
some extra logging. Briefly, it allows all (useful) outgoing
connections, blocks all incoming apart from a few incoming ports,
nothing fancy. After googling around for a while I found the following
mantra: -

iptables -A PREROUTING -t nat -p tcp -d $OUTSIDE_IP --dport 80 -j DNAT
--to $WEB_SERVER:80

iptables -A FORWARD -p tcp -d $WEB_SERVER --dport 80 -j ACCEPT

iptables -A POSTROUTING -t nat -p tcp -s $INSIDE_NETWORK/24 -d
$WEB_SERVER --dport 80 -j SNAT --to $INSIDE_IP

So I assume I need to intervene prior to allowing all outgoing traffic,
add a rule to PREROUTING where the destination is port 80 on our
external IP and nat to the web server port 80. Then, add forwarding and
postrouting rules. One potential problem is that, so far, the script has
no implicit knowledge of the external IP (assigned by NTL cable modem
via DHCP) or subnetwork definition as used by the above.

Ideas anyone?

Regards,
Michael.

-- 
Stability itself is nothing else than a more sluggish motion.





More information about the Nottingham mailing list