Raspberry Pi Zero as Ethernet Gadget Part 2: Routing to the Outside World
I wrote some time ago about how to use a Raspberry Pi over USB as an "Ethernet Gadget". It's a handy way to talk to a headless Pi Zero or Zero W if you're somewhere where it doesn't already have a wi-fi network configured.
However, the setup I gave in that article doesn't offer a way for the Pi Zero to talk to the outside world. The Pi is set up to use the machine on the other end of the USB cable for routing and DNS, but that doesn't help if the machine on the other end isn't acting as a router or a DNS host.
A lot of the ethernet gadget tutorials I found online explain how to do this on Mac and Windows, but it was tough to find an example for Linux. The best I found was for Slackware, How to connect to the internet over USB from the Raspberry Pi Zero, which should work on any Linux, not just Slackware.
Let's assume you have the Pi running as a gadget and you can talk to it, as discussed in the previous article, so you've run:
sudo ip a add 192.168.7.1/24 dev enp0s20u1 sudo ip link set dev enp0s20u1 upsubstituting your network number and the interface name that the Pi created on your Linux machine, which you can find in
dmesg | tail
or ip link
. (In Part 3
I'll talk more about how to find the right interface name
if it isn't obvious.)
At this point, the network is up and you should be able to ping the Pi
with the address you gave it, assuming you used a static IP:
ping 192.168.7.2
If that works, you can ssh to it, assuming you've enabled ssh.
But from the Pi's end, all it can see is your machine; it can't
get out to the wider world.
For that, you need to enable IP forwarding and masquerading:
sudo sh -c 'echo 1 > /proc/sys/net/ipv4/ip_forward' sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
Now the Pi can route to the outside world, but it still doesn't have DNS so it can't get any domain names. To test that, on the gateway machine try pinging some well-known host:
$ ping -c 2 google.com PING google.com (216.58.219.110) 56(84) bytes of data. 64 bytes from mia07s25-in-f14.1e100.net (216.58.219.110): icmp_seq=1 ttl=56 time=78.6 ms 64 bytes from mia07s25-in-f14.1e100.net (216.58.219.110): icmp_seq=2 ttl=56 time=78.7 ms --- google.com ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1001ms rtt min/avg/max/mdev = 78.646/78.678/78.710/0.032 ms
Take the IP address from that -- e.g. 216.58.219.110 -- then go to a shell
on the Pi and try ping -c 2 216.58.219.110
, and you should
see a response.
DNS with a Public DNS Server
Now all you need is DNS. The easy way is to use one of the free DNS services, like Google's 8.8.8.8. Edit /etc/resolv.conf and add a line like
nameserver 8.8.8.8and then try pinging some well-known hostname.
If it works, you can make that permanent by editing /etc/resolv.conf, and adding this line:
name_servers=8.8.8.8
Otherwise you'll have to do it every time you boot.
Your Own DNS Server
But not everyone wants to use public nameservers like 8.8.8.8. For one thing, there are privacy implications: it means you're telling Google about every site you ever use for any reason.
Fortunately, there's an easy way around that, and you don't even have to figure out how to configure bind/named. On the gateway box, install dnsmasq, available through your distro's repositories. It will use whatever nameserver you're already using on that machine, and relay it to other machines like your Pi that need the information. I didn't need to configure it at all; it worked right out of the box.
In the next article, Part 3: more about those crazy interface names (why is it enp0s20u1 on my laptop but enp0s26u1u1i1 on my desktop?), how to identify which interface is the gadget by using its MAC, and how to put it all together into a shell function so you can set it up with one command.
[ 15:25 Aug 31, 2018 More linux | permalink to this entry | ]