{"id":191,"date":"2020-09-26T13:17:46","date_gmt":"2020-09-26T13:17:46","guid":{"rendered":"https:\/\/dft.wiki\/?p=191"},"modified":"2026-06-09T15:00:13","modified_gmt":"2026-06-09T19:00:13","slug":"ubuntu-and-raspbian-as-a-gateway","status":"publish","type":"post","link":"https:\/\/dft.wiki\/?p=191","title":{"rendered":"Setting Up Ubuntu or Raspbian as a Gateway"},"content":{"rendered":"<p>This post will show how to share the Internet between two network adapters on Ubuntu Desktop 18.04 (any architecture) and Raspbian Buster 10 (for Raspberry Pi).<\/p>\n<p>The most common situation is when your device (a laptop or Raspberry Pi) is connected to the Internet via WiFi and you want to share this connection with another device via Ethernet (port RJ45), such as a Smart TV or a desktop that has no integrated WiFi.<\/p>\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" class=\"wp-image-270\" src=\"https:\/\/dft.wiki\/wp-content\/uploads\/sites\/15\/2020\/09\/image-99.png\" alt=\"\" \/><\/figure>\n<p>What is necessary:<\/p>\n<ul class=\"is-style-default\">\n<li>WiFi already set up with Internet access.<\/li>\n<li>Laptop or Raspberry Pi with a wireless card<\/li>\n<li>Linux operating system (Ubuntu or Raspbian)<\/li>\n<li>Ethernet cable<\/li>\n<li>The device you want to connect (TV, computer, printer, etc.)<\/li>\n<\/ul>\n<p>What will be configured:<\/p>\n<ul class=\"is-style-default\">\n<li>Configure the NIC (network adapter)<\/li>\n<li>Install a DHCP server (auto-assigns IPs) [<a href=\"https:\/\/www.youtube.com\/watch?v=S43CFcpOZSI\">learn more<\/a> &#8211; CertBros]<\/li>\n<li>Configure NAT (routing) [<a href=\"https:\/\/www.youtube.com\/watch?v=qij5qpHcbBk\">learn more<\/a> &#8211; CertBros]<\/li>\n<li>Install a DNS server (optional) [<a href=\"https:\/\/www.youtube.com\/watch?v=Rck3BALhI5c\">learn more<\/a> &#8211; Techquickie]<\/li>\n<\/ul>\n<p><strong>Configuring the NIC<\/strong><\/p>\n<pre>ip a<\/pre>\n<p class=\"has-text-color has-background has-accent-color has-subtle-background-background-color\"><strong>1: lo: <\/strong><em>&lt;omitted unnecessary text&gt;<\/em><br \/>\ninet 127.0.0.1\/8 scope host lo<br \/>\n<em> &lt;omitted unnecessary text&gt;<\/em><br \/>\n<strong> 2: eth0: <\/strong><em>&lt;omitted unnecessary text&gt;<\/em><br \/>\ninet <strong>172.16.1.1\/24<\/strong> brd 172.16.1.255 scope global noprefixroute eth0<br \/>\n<em>&lt;omitted unnecessary text&gt;<\/em><br \/>\n<strong> 3: wlan0:<\/strong> &lt;omitted unnecessary text&gt;<br \/>\ninet <strong>192.168.2.40\/24<\/strong> brd 192.168.2.255 scope global <strong>dynamic<\/strong> noprefixroute wlan0<br \/>\n<em>&lt;omitted unnecessary text&gt;<\/em><\/p>\n<p><strong>1: lo:<\/strong> The loopback interface. Ignore this virtual interface.<\/p>\n<p><strong>2: eth0:<\/strong> The Ethernet adapter that will be connected to the TV, computer, printer, etc.<\/p>\n<p><strong>3: wlan0:<\/strong> The wireless adapter that must be connected to your WiFi with a working Internet connection.<\/p>\n<p>Note: Interface names may vary. In this example, <strong>eth0 (LAN)<\/strong> and <strong>wlan0 (WAN)<\/strong>.<\/p>\n<p>In this example, <strong>eth0 is already manually configured<\/strong>.<\/p>\n<p>On Ubuntu, configure eth0 using the graphical interface as shown below:<\/p>\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" class=\"wp-image-273\" src=\"https:\/\/dft.wiki\/wp-content\/uploads\/sites\/15\/2020\/09\/image-4.png\" alt=\"\" \/><\/figure>\n<p>On Raspbian, configure eth0 via the terminal by editing \/etc\/dhcpcd.conf:<\/p>\n<pre>sudo nano \/etc\/dhcpcd.conf<\/pre>\n<p>Add this code at the end of the file:<\/p>\n<pre>interface eth0\r\nstatic ip_address=172.16.1.1\/24\r\nnogateway<\/pre>\n<p>Restart the computer after making this change.<\/p>\n<p>Pay attention to the IPs in the new scenario:<\/p>\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" class=\"wp-image-279\" src=\"https:\/\/dft.wiki\/wp-content\/uploads\/sites\/15\/2020\/09\/image-7.png\" alt=\"\" \/><\/figure>\n<p>Regardless of whether you are setting up a laptop + TV or a Raspberry Pi + PC, pay attention to the color-coded IPs. All orange IPs are in the same subnet; blue and green IPs belong to other subnets.<\/p>\n<p>The TV and PC each need an IP to communicate on the subnet. You can either configure each device manually or let them get an IP automatically via DHCP.<\/p>\n<p><strong>Installing the DHCP Server<\/strong><\/p>\n<pre>sudo apt-get update\r\nsudo apt-get install isc-dhcp-server -y\r\nsudo nano \/etc\/default\/isc-dhcp-server<\/pre>\n<p>Set the network adapter that DHCP will serve (LAN):<\/p>\n<pre>INTERFACESv4=\"<strong>eth0<\/strong>\"<\/pre>\n<p>Edit the configuration file:<\/p>\n<pre>sudo nano \/etc\/dhcp\/dhcpd.conf<\/pre>\n<p>Clear the file and replace it with this:<\/p>\n<pre>default-lease-time 600;\r\nmax-lease-time 7200;\r\noption subnet-mask 255.255.255.0;\r\noption broadcast-address 172.16.1.255;\r\noption routers 172.16.1.1;\r\noption domain-name-servers 8.8.8.8, 8.8.4.4;\r\noption domain-name \"host.local\";\r\nsubnet 172.16.1.0 netmask 255.255.255.0 {\r\nrange 172.16.1.10 172.16.1.100;\r\n}<\/pre>\n<p>Run the following commands:<\/p>\n<pre>sudo systemctl restart isc-dhcp-server\r\nsudo systemctl enable isc-dhcp-server\r\nsudo systemctl status isc-dhcp-server<\/pre>\n<p>The second command may fail on Raspbian. That is fine, just continue.<\/p>\n<p>Verify that the service is ACTIVE (shown in green):<\/p>\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" class=\"wp-image-280\" src=\"https:\/\/dft.wiki\/wp-content\/uploads\/sites\/15\/2020\/09\/image-8.png\" alt=\"\" \/><\/figure>\n<p>Devices can now get their IP configuration automatically:<\/p>\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" class=\"wp-image-281\" src=\"https:\/\/dft.wiki\/wp-content\/uploads\/sites\/15\/2020\/09\/image-9.png\" alt=\"\" \/><\/figure>\n<p>All of this configuration is customizable. In the example above, the laptop and the Raspberry Pi intentionally share the same IP address range, but they are on physically separate networks. The same applies to the TV and PC; they may both receive the first available IP from their respective DHCP servers. Verify that each device received its IP correctly.<\/p>\n<p><strong>Configuring NAT (for Ubuntu):<\/strong><\/p>\n<pre>sudo ufw enable\r\nsudo nano \/etc\/ufw\/sysctl.conf<\/pre>\n<p>Uncomment the following line, or add it if it is not present:<\/p>\n<pre>net\/ipv4\/ip_forward=1<\/pre>\n<p>Do the same in <strong>\/etc\/sysctl.conf<\/strong>.<\/p>\n<p>Edit the startup script:<\/p>\n<pre>sudo nano \/etc\/rc.local<\/pre>\n<p>Paste this content into the file:<\/p>\n<pre>#!\/bin\/bash\r\niptables -P INPUT DROP\r\niptables -P FORWARD DROP\r\niptables -A INPUT -i lo -j ACCEPT\r\niptables -A INPUT -i eth0 -j ACCEPT\r\niptables -A INPUT -i wlan0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT\r\n<em>iptables -t nat -A PREROUTING -p tcp -d <strong>192.168.2.40<\/strong> --dport <strong>80<\/strong> -j DNAT --to-destination <strong>172.16.1.10<\/strong><strong>:80<\/strong><\/em>\r\niptables -A FORWARD -i eth0 -o wlan0 -j ACCEPT\r\niptables -A FORWARD -i wlan0 -o eth0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT\r\niptables -t nat -A POSTROUTING -j MASQUERADE\r\nexit 0<\/pre>\n<p>Note: the italicized line in the middle is a template for Static NAT (Port Forwarding). Replace <strong>192.168.2.40<\/strong> with your public IP and <strong>172.16.1.10<\/strong> with your private IP (a web server in this case, on port <strong>80<\/strong>). If you are not using port forwarding, simply delete that line. See the illustration below:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-601 size-full\" src=\"https:\/\/dft.wiki\/wp-content\/uploads\/sites\/15\/2020\/09\/image-9_.png\" alt=\"\" width=\"720\" height=\"255\" srcset=\"https:\/\/dft.wiki\/wp-content\/uploads\/sites\/15\/2020\/09\/image-9_.png 720w, https:\/\/dft.wiki\/wp-content\/uploads\/sites\/15\/2020\/09\/image-9_-300x106.png 300w\" sizes=\"auto, (max-width: 720px) 100vw, 720px\" \/><\/p>\n<p>Make the file executable:<\/p>\n<pre>sudo chmod 755 \/etc\/rc.local<\/pre>\n<p><strong>Configuring NAT (for Raspbian):<\/strong><\/p>\n<pre>sudo nano \/etc\/rc.local<\/pre>\n<p>Add this code at the end of the file, <strong>right before<\/strong> the last line: <strong>exit 0<\/strong><\/p>\n<pre>iptables -A INPUT -i lo -j ACCEPT\r\niptables -A INPUT -i eth0 -j ACCEPT\r\niptables -A INPUT -i wlan0 -m conntrack \\\r\n--ctstate ESTABLISHED,RELATED -j ACCEPT\r\niptables -A FORWARD -i eth0 -o wlan0 -j ACCEPT\r\niptables -A FORWARD -i wlan0 -o eth0 -m conntrack \\\r\n--ctstate ESTABLISHED,RELATED -j ACCEPT\r\niptables -t nat -A POSTROUTING -j MASQUERADE\r\nsystemctl start isc-dhcp-server<\/pre>\n<p><strong>Restart Ubuntu\/Raspbian<\/strong> for the changes to take effect, then verify that the <strong>TV and\/or PC have Internet access<\/strong>.<\/p>\n<p><strong>Installing the DNS Server (optional)<\/strong><\/p>\n<p>With the current configuration, the DHCP server automatically points devices (TV, PC, printer, etc.) to Google&#8217;s public DNS servers (8.8.8.8 and 8.8.4.4). Another option is to use your wireless router&#8217;s DNS server (in this example, 192.168.2.1).<\/p>\n<p>You can also set up your own private DNS server for full control. This lets you apply blacklists or whitelists for parental controls, business policies, or any other purpose.<\/p>\n<pre>sudo apt install bind9 -y\r\nsudo nano \/etc\/bind\/named.conf.options<\/pre>\n<p>Replace the entire file content with:<\/p>\n<pre>options{\r\ndirectory \"\/var\/cache\/bind\";\r\nrecursion yes;\r\nforwarders {\r\n8.8.8.8;\r\n8.8.4.4;\r\n};\r\nforward only;\r\n};<\/pre>\n<p>Note: the DNS server forwards requests it does not know how to resolve. After the first lookup, it caches the result for faster responses going forward.<\/p>\n<p>Restart the DNS and DHCP servers:<\/p>\n<pre>sudo systemctl restart bind9\r\nsudo systemctl restart isc-dhcp-server.service<\/pre>\n<p>Now restart all connected devices so they request a new configuration from the DHCP server and begin using the local DNS server.<\/p>\n<p><strong>Everything is set up and running!<\/strong><\/p>\n<p>To reserve a specific IP for a device, append the following to <strong>\/etc\/dhcp\/dhcpd.conf<\/strong>:<\/p>\n<pre>host mytv {\r\nhardware ethernet A4:BA:DB:14:BD:4F;\r\nfixed-address 192.168.110.10;\r\n}<\/pre>\n<hr \/>\n<p><strong>BONUS<\/strong><\/p>\n<p>For port forwarding on a single network interface:<\/p>\n<pre>#!\/bin\/bash\r\niptables -P INPUT DROP\r\niptables -P FORWARD DROP\r\niptables -A INPUT -i lo -j ACCEPT\r\niptables -A INPUT -i <strong>eth0<\/strong> -j ACCEPT\r\niptables -t nat -A PREROUTING -p tcp -d <span style=\"color: #ff0000;\"><strong>192.168.1.5<\/strong><\/span> --dport <span style=\"color: #0000ff;\"><strong>443<\/strong><\/span> -j DNAT --to-destination <strong><span style=\"color: #ff0000;\">192.168.1.50<\/span><\/strong>:<strong><span style=\"color: #0000ff;\">443<\/span><\/strong>\r\niptables -A FORWARD -s <span style=\"color: #ff0000;\"><strong>192.168.1.0<\/strong><\/span>\/<strong>24<\/strong> -j ACCEPT\r\niptables -t nat -A POSTROUTING -j MASQUERADE\r\nexit 0<\/pre>\n<p>Alternatively, use <strong>nftables<\/strong> to manage <strong>iptables<\/strong> rules:<\/p>\n<pre>sudo ufw disable\r\nsudo systemctl disable ufw\r\nsudo apt install nftables -y\r\nsudo systemctl enable nftables\r\nsudo sed -i 's\/#net.ipv4.ip_forward=1\/net.ipv4.ip_forward=1\/g' \/etc\/sysctl.conf\r\nsudo sysctl -p\r\nsudo nft list ruleset\r\nsudo nft flush ruleset\r\nsudo nft list ruleset\r\nsudo nft flush ruleset\r\nsudo nft add table nat\r\nsudo nft 'add chain nat postrouting { type nat hook postrouting priority 100 ; }'\r\nsudo nft 'add chain nat prerouting { type nat hook prerouting priority -100; }'\r\nsudo nft 'add rule nat prerouting ip daddr <span style=\"color: #ff0000;\"><strong>192.168.1.5<\/strong><\/span> tcp dport { <span style=\"color: #0000ff;\"><strong>21<\/strong><\/span> } dnat <strong><span style=\"color: #ff0000;\">192.168.1.50<\/span><\/strong>:<span style=\"color: #0000ff;\"><strong>21<\/strong><\/span>'\r\nsudo nft 'add rule nat prerouting ip daddr <span style=\"color: #ff0000;\"><strong>192.168.1.5<\/strong><\/span> tcp dport { <strong><span style=\"color: #0000ff;\">60000-65000<\/span><\/strong> } dnat <strong><span style=\"color: #ff0000;\">192.168.1.50<\/span><\/strong>:<span style=\"color: #0000ff;\"><strong>60000-65000<\/strong><\/span>'\r\nsudo nft add rule nat postrouting masquerade\r\nsudo nft list ruleset | sudo tee \/etc\/nftables.conf<\/pre>\n<p>To manage rules:<\/p>\n<pre>sudo nft -a list table nat\r\nsudo nft delete rule nat prerouting handle 7<\/pre>\n<p>How to configure NAT with <strong>nftables<\/strong>:<\/p>\n<pre>sudo nano \/etc\/sysctl.conf<\/pre>\n<pre>net.ipv4.ip_forward = 1<\/pre>\n<pre>sudo nano \/etc\/nftables.conf<\/pre>\n<pre>table inet nat {\r\n    chain prerouting {\r\n        type nat hook prerouting priority -100; policy accept;\r\n    }\r\n    chain postrouting {\r\n        type nat hook postrouting priority 100; policy accept;\r\n        oifname \"eth0\" masquerade\r\n    }\r\n}\r\ntable inet filter {\r\n    chain forward {\r\n        type filter hook forward priority 0; policy drop;\r\n        iifname \"eth1\" oifname \"eth0\" accept\r\n        ct state established,related accept\r\n    }\r\n}<\/pre>\n<pre>sudo sysctl -p\r\nsudo nft -f \/etc\/nftables.conf<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>This post will show how to share the Internet between two network adapters on Ubuntu [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4,6],"tags":[],"class_list":["post-191","post","type-post","status-publish","format-standard","hentry","category-linux","category-raspberry-pi"],"_links":{"self":[{"href":"https:\/\/dft.wiki\/index.php?rest_route=\/wp\/v2\/posts\/191","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dft.wiki\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dft.wiki\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dft.wiki\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dft.wiki\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=191"}],"version-history":[{"count":19,"href":"https:\/\/dft.wiki\/index.php?rest_route=\/wp\/v2\/posts\/191\/revisions"}],"predecessor-version":[{"id":5849,"href":"https:\/\/dft.wiki\/index.php?rest_route=\/wp\/v2\/posts\/191\/revisions\/5849"}],"wp:attachment":[{"href":"https:\/\/dft.wiki\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=191"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dft.wiki\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=191"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dft.wiki\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=191"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}