How do I set up an Ubuntu server to be the router for two private networks on my network, and do the DHCP addressing?

14,213

NOTE #1: This is to set up the most basic setup possible - a straight router for two or more subnets, without restricting cross-subnet traffic at all. This can be changed with firewall rules to better handle control of individual functions or network access across subnets or outboud to the internet, however that is beyond the scope of this basic "set it up" Q/A pair.

NOTE #2: At the time this answer was written, Ubuntu did not yet use Netplan for its networking control system for default setups. This answer was as such written without taking Netplan into account.

You'll need an Ubuntu server with 3 network interfaces, of course, one for the Internet-connected interface, and two private network interfaces.

After that, just follow this guide to setup this server as a router:

(1) Edit /etc/sysctl.conf. Find and uncomment this line:

net.ipv4.ip_forward=1

Once you've done this, execute the command sudo sysctl -p to reload the system kernel settings. This allows the Ubuntu box to now serve traffic across subnets and VLANs via IPv4.

(2) Edit your router box's /etc/network/interfaces to set up the static IP address on the interfaces which serve the private networks. In this example, I know the interfaces are ens37 and ens38, while ens33 is the primary Internet connected interface on my box. I'm leaving ens33 alone, but adding ens37 and ens38 configuration stanzas:

# Private Subnet 1
auto ens37
iface ens37 inet static
    address 10.76.100.1
    netmask 255.255.255.0
    dns-nameservers 8.8.8.8 8.8.4.4

# Private Subnet 2
auto ens38
iface ens38 inet static
    address 10.76.101.1
    netmask 255.255.255.0
    dns-nameservers 8.8.8.8 8.8.4.4

Adjust the network addresses and interface names accordingly for your setup.

**Note that if you are using VMware Workstation or similar, and you have vmnet# devices selected in the VM for this, make sure the host system either does NOT have a host-attached device for this vmnet, or that if it does, you use a different address than .1 in the last octet on your router box.

(3) Install the DHCP server software. We'll configure this in later steps.

sudo apt-get install isc-dhcp-server

This will permit the router box to serve DHCP requests for your private subnets.

(4) First, copy the DHCP Server config that was installed automatically to a backup file.

sudo cp /etc/dhcp/dhcpd.conf /etc/dhcp/dhcpd.conf.dist

(5) Now, we are making that original file blank so we can apply our config.

echo "" | sudo tee /etc/dhcp/dhcpd.conf

(6) Now let's use our config:

# DHCP Server config

# The ddns-updates-style parameter controls whether or not the server will
# attempt to do a DNS update when a lease is confirmed. We default to the
# behavior of the version 2 packages ('none', since DHCP v2 didn't
# have support for DDNS.)
ddns-update-style none;

# If this DHCP server is the official DHCP server for the local
# network, the authoritative directive should be uncommented.
authoritative;

# Use this to send dhcp log messages to a different log file (you also
# have to hack syslog.conf to complete the redirection).
log-facility local7;

# Specify the domain name servers to specify for each subnet.
option domain-name-servers 8.8.8.8;
option domain-name-servers 8.8.4.4;


# DHCP Subnet configurations

# Subnet 1 - ens37
subnet 10.76.100.0 netmask 255.255.255.0 {
  default-lease-time 86400;
  max-lease-time 86400;

  range 10.76.100.10 10.76.100.200;
  option routers 10.76.100.1;
  option subnet-mask 255.255.255.0;
  option broadcast-address 10.76.100.255;
}

# Subnet 2 - ens38
subnet 10.76.101.0 netmask 255.255.255.0 {
  default-lease-time 86400;
  max-lease-time 86400;

  range 10.76.101.10 10.76.101.200;
  option routers 10.76.101.1;
  option subnet-mask 255.255.255.0;
  option broadcast-address 10.76.101.255;
}

Adjust this config accordingly to your needs, and make sure to update the 'routers' option based on whatever IP address you set above in your network configuration settings.

Once you're done adjusting the file as needed, save the file.

(7) We need to tell the system what interfaces to care about. Edit /etc/default/isc-dhcp-server, and specify your private network interfaces (in my case, ens37 and 38) in the INTERFACES="" line, so that it'd look like this:

INTERFACES="ens37 ens38"

Save the file.

(8) And now, the firewall rules. We need to tell the system to permit the thing to work as a router, and set up proper controls and rulesets for this to be the case. I'm assuming you haven't configured the firewall here, because I'm describing a from-scratch setup.

If you have already set up ufw on this machine, run sudo ufw disable, and then uninstall ufw with sudo apt-get remove ufw. UFW does not work for what we need, we need the advanced power of iptables directly. For most routers we should not be using UFW at all.

Make sure we know the interface name for your Internet-connected network interface. On my example test system, it was ens33, but it may be different on your system. Make sure we also know the network interfaces for our private networks we're going to be the router for; we need them in here too. Setup your iptables as follows with the following commands. Pay attention to my comments as well:

# Accept localhost traffic (local traffic to the system itself)
sudo iptables -A INPUT -i lo -j ACCEPT

# Accept all traffic related to established connections
sudo iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

# Drop traffic coming from the Internet into our Internet-connected interface (except for traffic related to other established connections)
# Update this to match the interface name of your Internet-connected interface.
sudo iptables -A INPUT -i ens33 -j DROP

# Accept traffic inbound from the local subnets we are acting as a router for.
# CHANGE THESE INTERFACE NAMES ACCORDING TO YOUR SETUP!
sudo iptables -A INPUT -i ens37 -j ACCEPT
sudo iptables -A INPUT -i ens38 -j ACCEPT

# Since we don't want to have our system completely open to the Internet, we need
# to drop all other traffic coming to our network.  This way, we can prevent the
# Internet at large from accessing our network directly from the Internet.
sudo iptables -A INPUT -j DROP

# Add rules to accept forwarding on the interfaces we are doing routing for.
# CHANGE THESE INTERFACE NAMES ACCORDING TO YOUR SETUP!
sudo iptables -A FORWARD -i ens37 -j ACCEPT
sudo iptables -A FORWARD -o ens37 -j ACCEPT
sudo iptables -A FORWARD -i ens38 -j ACCEPT
sudo iptables -A FORWARD -o ens38 -j ACCEPT

# Add rules to the NAT table to allow us to actually let traffic on the interfaces
# which we are doing routing for go out to the Internet masquerade as our Internet-
# connected interface.
#
# ADJUST THE IP RANGES HERE TO MATCH THE IP RANGES AND THE SUBNETS FOR YOUR OWN
# ENVIRONMENT!  Remember that the IP address of 10.76.100.1 for the router, and
# the netmask 255.255.255.0 is equal to the network range/CIDR of 10.76.100.0/24
# for the purposes of these rules.
sudo iptables -t nat -A POSTROUTING -s 10.76.100.0/24 ! -d 10.76.100.0/24 -j MASQUERADE
sudo iptables -t nat -A POSTROUTING -s 10.76.101.0/24 ! -d 10.76.101.0/24 -j MASQUERADE

(9) Install the iptables-persistent package which will allow us to actually remember our iptables rules and load them at reboot.

sudo apt-get install iptables-persistent`

When it asks to save the existing rules, select "Yes" for both IPv4 and IPv6.

(10) Test it! Set up another system on one of the private networks you've configured, and make sure once it's set up that it can communicate to the Internet and has a configured DHCP address within the private subnets set up above!

Share:
14,213

Related videos on Youtube

Thomas Ward
Author by

Thomas Ward

Updated on September 18, 2022

Comments

  • Thomas Ward
    Thomas Ward over 1 year

    I want to use my Ubuntu server to be a router for two private networks on my network.

    I also want this server to serve DHCP requests for the private networks.

    How do I set up an Ubuntu 16.04 server to do this?

  • Doug Smythies
    Doug Smythies over 6 years
    For your ICMP line, shouldn't it be sudo iptables -A INPUT -p ICMP -i ens33 -j DROP? You left a hanging sentence For most routers we should not be using ?? Perhaps ufw is missing?
  • Thomas Ward
    Thomas Ward over 6 years
    @DougSmythies Technically yes, but we don't need to have a specific rule like that, if we explicitly allow the internal interfaces' traffic to reach the router box first and then just straight drop all other otherwise unmatched traffic including ICMP pings, and unauthorized port scans. Now, if we wanted to block ICMP from everywhere except one interface or IP, then yes we could technically to that extra step and make individual rulesets. The above, though, works as a basic ruleset.
  • Doug Smythies
    Doug Smythies over 6 years
    Then my suggestion is to delete the ICMP comment and change it to "DROP anything else incoming from internet" or similar. I gather the DHCP server knows which subnet based on which interface the lease request was submitted on. Cool.
  • Thomas Ward
    Thomas Ward over 6 years
    FWIW you have the ability to go hit "edit" and improve things. @DougSmythies Yes, it determines it by IP subnet, which is determined in the isc-dhcp-server config I include above in the individual subnet sections.