This document uses the terms "router" and "firewall" interchangeably. A firewall is just a router that does filtering based on the packets. (Unfortunately, some companies have started using the term firewall for something totally different that filters packets inside the system. While they may be better than nothing, such partitions are flimsy and tend to fall over.)
In most Internet books, you'll see diagrams like the following for a router:
Internet ========================== | ----------------- | external IP | | | | router | | | | internal IP | ----------------- | ================= | | | internal subnetand they will explain the internal and external addresses need to be on separate networks.
In this document, I show one way of making this:
Internet ========================== | ----------------- | single IP | | | | router | | | | same IP | ----------------- | ================= | | | assigned subnetor even:
Internet
==========================
|
-----------------
| single IP |
| |
| router |
| |
|same IP same IP|
-----------------
| |
================= ================
| | | | | |
first subnet second subnet
where the internal subnets can be of arbitrary sizes, (no power of two
limitations), only the router needs to know the messy details, and
your ISP has only given you a single subnet and doesn't need to know
you have a firewall.
The hardest part of the single-address router is throwing away the preconceived notions about how IP works. As long as every system that the netmask shows being on the same subnet is reachable via arp, there is no need for it to actually be the same subnet. A system may use the same IP address on multiple interfaces as long as it knows which one to use to get to any given system.
The next problem is the (normally desirable) side effects the
ifconfig and route commands have.
Fortunately, linux has the ip command that allows much
more control of the details. This is in the iproute
package in Debian, users of
Proxy arp, another piece of the puzzle, has been around for years, but doesn't fit well with the classical model of how an IP network should work. Modern linux will proxy arp for any address it knows how to route to when it is enabled.
The only program I have found to have a problem with multiple interfaces having the same IP address is dhcpd. The workaround I am currently using is to use another IP address on one of my subnets. (The firewall in question is also the dhcp server for two subnets.) The proper solution is to change the dhcpd code not to assume that the IP address uniquely determine the interface.
The solution documented here has been in production for about a year on a network with 200 users split into 5 subnets and a 45mbps internet connection. The /24 was in use before the firewall went in, and the addresses were only partly grouped by subnet. Rather than renumbering, I opted for complicated routing tables on the firewall.
The following examples include shell scripts to do the entire interface configuration. The interfaces controlled by these scripts should not be initialized elsewhere, such as /etc/network/interfaces in Debian. You'll need to run the script upon system reboot.
ISP gave us 10.0.130.224/27. Their router is at 10.0.130.254. Our firewall is 10.0.130.253, and we want as many routable IPs usable as possible. eth0 is connected to their router, and eth1 to the internal network. Usable addresses are 10.0.130.225-10.0.130.252. 10.0.130.224 may be usable if the ISPs router doesn't mind. The systems should be set up as if they were in 10.0.130.224/27 and can use either 10.0.130.253 or 10.0.130.254 as the default route.
#!/bin/sh
# turn of routing while configuring/reconfiguring
echo 0 >/proc/sys/net/ipv4/ip_forward
# define the interfaces. Like ifconfig, but no routes done
ip link set dev eth0 up
ip link set dev eth1 up
ip address add dev eth0 local 10.0.130.253/32 broadcast 10.0.130.255
ip address add dev eth1 local 10.0.130.253/32 broadcast 10.0.130.255
# iptables setup goes here
# set up routes. src is used only on packets originating here.
ip route add 10.0.130.224/28 dev eth1 src 10.0.130.253
ip route add 10.0.130.240/29 dev eth1 src 10.0.130.253
ip route add 10.0.130.248/30 dev eth1 src 10.0.130.253
ip route add 10.0.130.252/32 dev eth1 src 10.0.130.253
ip route add 10.0.130.254/32 dev eth0 src 10.0.130.253
# default route needs to be done after the route it is via
ip route add 0/0 via 10.0.130.254 dev eth0 src 10.0.130.253
# turn on forwarding, proxy arp, and rp_filter
echo 1 >/proc/sys/net/ipv4/ip_forward
for dev in default eth0 eth1
do
echo 1 >/proc/sys/net/ipv4/conf/${dev}/proxy_arp
echo 1 >/proc/sys/net/ipv4/conf/${dev}/rp_filter
done
Like example 1, except now we have 3 systems via eth1, 13 via eth2, and the rest via eth3.
#!/bin/sh
# turn of routing while configuring/reconfiguring
echo 0 >/proc/sys/net/ipv4/ip_forward
# define the interfaces. Like ifconfig, but no routes done
ip link set dev eth0 up
ip link set dev eth1 up
ip link set dev eth2 up
ip link set dev eth3 up
ip address add dev eth0 local 10.0.130.253/32 broadcast 10.0.130.255
ip address add dev eth1 local 10.0.130.253/32 broadcast 10.0.130.255
ip address add dev eth2 local 10.0.130.253/32 broadcast 10.0.130.255
ip address add dev eth3 local 10.0.130.253/32 broadcast 10.0.130.255
# iptables setup goes here
# set up routes. src is used only on packets originating here.
ip route add 10.0.130.224/30 dev eth1 src 10.0.130.253
ip route add 10.0.130.228/30 dev eth2 src 10.0.130.253
ip route add 10.0.130.232/29 dev eth2 src 10.0.130.253
ip route add 10.0.130.240/32 dev eth2 src 10.0.130.253
ip route add 10.0.130.241/32 dev eth3 src 10.0.130.253
ip route add 10.0.130.242/31 dev eth3 src 10.0.130.253
ip route add 10.0.130.244/30 dev eth3 src 10.0.130.253
ip route add 10.0.130.248/30 dev eth3 src 10.0.130.253
ip route add 10.0.130.252/32 dev eth3 src 10.0.130.253
ip route add 10.0.130.254/32 dev eth0 src 10.0.130.253
# default route needs to be done after the route it is via
ip route add 0/0 via 10.0.130.254 dev eth0 src 10.0.130.253
# turn on forwarding, proxy arp, and rp_filter
echo 1 >/proc/sys/net/ipv4/ip_forward
for dev in default eth0 eth1 eth2 eth3
do
echo 1 >/proc/sys/net/ipv4/conf/${dev}/proxy_arp
echo 1 >/proc/sys/net/ipv4/conf/${dev}/rp_filter
done