How can I use Linux as a Gateway?

You are almost there you just need to make sure traffic gets back to B. Right now you have forwarded traffic from B to the outside world but A doesn't know how to get traffic back to B. You need A to keep some state about the connections going through it. To do this you will want to enable NAT. You already have step one which is allow forwarding. Then you need to add a few firewall rules using iptables:

iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

This says: on the network address translation table, after we have figured out the routing of a packet on output eth0 (the external), replace the return address information with our own so the return packets come to us. Also, remember that we did this (like a lookup table that remembers this connection).

iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT

Allow packets that want to come from eth1 (the internal interface) to go out eth0 (the external interface).

iptables -A FORWARD -i eth0 -o eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT

Use that lookup table we had from before to see if the packet arriving on the external interface actually belongs to a connection that was already initiated from the internal.


In order to have routing work correctly between two Linux computers acting as gateways, there are several things that need to be in place:

  • Both gateways need to have a physical link to each other (or virtual if you are linking virtual machines).
  • Routes must be added to both interfaces on the router.

    route add -net 192.168.0.0/24 gw 192.168.0.1
    route add -net 192.168.1.0/24 gw 192.168.1.1
    
  • A local gateway must be specified for the remote network on both gateways. This allows computers on the local network to know where to send packets for the remote network. The gateway should be the IP address of the computer that will send packets to the remote network.

  • Computers wishing to send traffic between the networks must also be made aware of what local gateway is handling traffic to and from the remote network. This is usually done via Dynamic Host Control Protocol (DHCP), however if you intend to use a separate gateway for the internet you will need to specify both on the computers needing access to both the Internet and the other network (e.g. the Internet gateway via DHCP and the other network's gateway via a route).
  • IP forwarding must be active for both gateways.
  • IP Masquerading must be enabled to allow NAT to function between the gateways.

    modprobe iptable_nat
    echo 1 > /proc/sys/net/ipv4/ip_forward
    iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
    iptables -A FORWARD -i eth1 -j ACCEPT
    

    You may need to specify a source and destination since you are using the same interface for masquerading:

    iptables -t nat -A POSTROUTING -i eth0 -s 192.168.0.0/24 ! -d 192.168.1.0/24 -j MASQUERADE
    

    and the other gateway:

    iptables -t nat -A POSTROUTING -i eth1 -s 192.168.1.0/24 ! -d 192.168.0.0/24 -j MASQUERADE   
    

    For each gateway, the local network traffic should be accepted on the appropriate interface like this:

    iptables -A FORWARD -i eth0 -s 192.168.0.0/24 -j ACCEPT
    

    or

    iptables -A FORWARD -i eth1 -s 192.168.1.0/24 -j ACCEPT
    

There are numerous links and similar questions able to be referenced for solving the problems you are having.

What appears to be wrong in this particular case is that route and gateway setup is not complete on on both computers and Network Address Translation (NAT) has not been enabled using iptables, allowing the gateways to carry the request from a computer on the other subnet on their behalf.

Doing this is also critical when setting up an internet connection as you are responsible for one end of the connection (e.g. using a Linux computer as a gateway for a PPPoE connection).