TODO: Create a standalone document by adding step-by-step procedures.

How to connect to the Internet over USB from the Raspberry Pi Zero

This How-To document explains how I managed to get an Internet connection to the Pi Zero over USB using a Windows 7 host PC, a Linux server, and a USB data cable. If the Internet connection sharing (ICS) option works without any issues on the host PC or a SSH server can be installed on the same PC, the Linux server is not required.

1   Windows 7

1.1   Create an SSH connection to the Pi Zero over USB

I was able to connect to the Raspberry Pi Zero using only a host PC and a USB data cable by following this article. I had to install the RNDIS/Ethernet Gadget driver as explained in this document to recognize the Pi Zero as an ethernet device. Not only that, I needed to install the Bonjour SDK for Windows to discover the little computer on the local network and connect to it by its name, not by a randomly assigned IP address. So far, so good.

1.2   Share the Internet with the Pi

One problem with this setting is that the Pi Zero doesn’t have an outgoing Internet connection, so I can only get into it through SSH and cannot come out to the Internet from there. One comment in the article suggests how to share the host PC’s Internet with the Pi Zero. Unfortunately, for whatever reason, I was getting a blue screen of death (BSOD) whenever I enable the Internet connection sharing (ICS) option on the host PC running Windows 7 and connect to the Pi Zero over USB. Updating the LAN device driver didn’t help. As a workaround, I used port forwarding over SSH to create a SOCKS5 proxy server and used tsocks as a proxy client. According to the INSTALL document of tsocks, it should be able to handle DNS queries over TCP protocols when compiled with –enable-socksdns --disable-hostnames, but these compile-time options didn’t help resolve DNS queries. As a result, the SOCKS5 client would only handle IP-based queries, which is not very useful. I found an article about this same issue, which also suggests a fix to the problem. By patching tsocks as recommended, I was able to send DNS queries out from the Pi Zero over USB.

1.3   Connect to the Pi from the proxy server

Now, if the proxy server is different from the host PC, to which the Pi Zero is connected via USB, there is no way to connect to the Raspberry from the proxy server because only the host PC can see it. For example, the Pi Zero (P) is connected to the host PC (H) and uses the proxy server (S) for outgoing traffic. I can SSH into P from H because P serves as a USB ethernet device for H, but I cannot connect to P from S because S has no physical connection to P and only serves as a SOCKS5 proxy server. To address this issue, I initiated two additional SSH tunnels:

  1. Remote port forwarding from S to H created on H
  2. Local port forwarding from H to P created on H

In this way, I was able to SSH into P from S through the two SSH tunnels above.

2   Slackware using Avahi

2.1   Create an SSH connection to the Pi Zero over USB

On the host,

  1. Install avahi with the –enable-autoipd configure option. The avahi package from SlackBuild doesn’t include this configure option.
  2. Install nss-mdns either manually or using sbopkg:
    sbopkg -i nss-mdns
  3. Copy /etc/nsswitch.conf-mdns to /etc/nsswitch.conf:
    cp /etc/nsswitch.conf-mdns /etc/nsswitch.conf
  4. Start the avahi daemon:
    /etc/rc.d/rc.avahidaemon start
  5. Assign an IP address to the USB device:
    avahi-autoipd -D usb0
  6. SSH into the Pi:
    ssh pi@raspberrypi.local

2.2   Share the Internet with the Pi

On the host,

  1. Find the IP address on usb0 (e.g., 169.254.1.1):
    ifconfig usb0:avahi
  2. Allow IP forwarding on the host:
    echo 1 > /proc/sys/net/ipv4/ip_forward
    iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
  3. SSH into the Pi: ssh pi@raspberrypi.local

On the Pi,

  1. Add a name server (e.g., 169.254.1.1 from the host) to /etc/resolv.conf:
    echo nameserver 169.254.1.1 | sudo tee /etc/resolv.conf
  2. Set the default gateway (e.g., 169.254.1.1) to the host PC’s IP address:
    sudo route add default gw 169.254.1.1

3   Slackware using a static IP address

On the Pi,

  1. Once a connection to the Pi using Avahi is established, SSH into the Pi.
  2. Disable the avahi service because it’s not needed for a static IP address:
    sudo systemctl disable avahi-daemon
  3. Add the following lines to /etc/network/interfaces:
    allow-hotplug usb0
    iface usb0 inet static
        address 192.168.2.2
        netmask 255.255.255.0
        network 192.168.2.0
        broadcast 192.168.2.255
        gateway 192.168.2.1
        dns-nameservers 8.8.8.8
  4. Reboot:
    sudo reboot

On the host,

  1. Assign an IP address to the usb0 device:
    ifconfig usb0 192.168.2.1
  2. Allow IP forwarding on the host:
    echo 1 > /proc/sys/net/ipv4/ip_forward
    iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
  3. SSH into the Pi:
    ssh pi@192.168.2.2

If you want to connect to the Pi in the 192.168.2.0 subnet from a computer in the 192.168.1.0 subnet, run the following command on the computer from which you want to connect to the Pi:

route add -net 192.168.2.0 netmask 255.255.255.0 gw 192.168.1.2

4   More ideas

It would be great if the Pi Zero appears as a mass storage on the host PC and contains programs required to create an Internet connection for itself. Maybe, adding the mass storage driver in Raspbian should do it.

5   References