2

In a project, I want to use Raspberry Pi Zero W as an USB wifi dongle to my USB Host(PC). Currently only station mode needed, but I would like it has AP mode either, just like a real Wifi Dongle. Is there anyway to do that through a few configuration steps? Or I have to write up a real linux usb gadget driver in C code to emulate a wifi card on RPi Zero W?

Ingo
  • 40,606
  • 15
  • 76
  • 189
  • Do you want to make an access point with the "dongle" or do you want to connect to a remote hotspot with it? – Ingo Apr 27 '19 at 07:34
  • Currently only station mode needed, but I would like it has AP mode either, just like a real Wifi Dongle. – esky-sh service Apr 28 '19 at 03:51

1 Answers1

4

I do not have a Raspberry Pi Zero W so I cannot test it with this hardware. But when you have established an OTG Gadget ether emulation with the USB connection then you have a virtual but regular interface that should be usable like any other ethernet interface. Afaik it has the name usb0 but to be a bit more generic for others I will name it eth0.

You want to use the RasPi as station. Then in principle you can use either routing or bridging. The problem is that the on-board wifi device does not support bridging a wifi client connection. For further information look at Raspberry Pi WiFi to Ethernet Bridge for a server?.

Use routing

I will show how I would use routing to connect a wired ethernet connection to a remote hotspot via wifi with systemd-networkd. The disadvantage of routing is that the subnet for eth0 must be different from that for wlan0. If not then the connection will not work. To reduce matching subnets I will make that for eth0 as small as possible from a pool as big as possible. That's from the class A private subnet 10.0.0.0/8.

For reference I use Raspbian Stretch Lite 2019-04-08 updated with sudo apt update && sudo apt full-upgrade && sudo reboot on 2019-04-28.

Example for this setup:

         wired                      wifi            wan
laptop <───────> (eth0)RPi(wlan0) <.~.~.~> hotspot <───> INTERNET
      \           /            \
    (dhcp    10.148.238.125   (dhcp
   from RPi)                from hotspot)

Switch over to systemd-networkd:

# disable classic networking
rpi ~$ sudo -Es
rpi ~# systemctl mask networking.service
rpi ~# systemctl mask dhcpcd.service
rpi ~# mv /etc/network/interfaces /etc/network/interfaces~
rpi ~# sed -i '1i resolvconf=NO' /etc/resolvconf.conf

# enable systemd-networkd
rpi ~# systemctl enable systemd-networkd.service
rpi ~# systemctl enable systemd-resolved.service
rpi ~# ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf

Configure wpa_supplicant with your settings for country=, ssid= and psk=:

rpi ~# cat > /etc/wpa_supplicant/wpa_supplicant-wlan0.conf <<EOF
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=DE

network={
    ssid="TestNet"
    psk="Password"
    key_mgmt=WPA-PSK
}
EOF

rpi ~# chmod 600 /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
rpi ~# systemctl disable wpa_supplicant.service
rpi ~# systemctl enable wpa_supplicant@wlan0.service

Configure interfaces with this files:

rpi ~# cat > /etc/systemd/network/04-eth0.network <<EOF
[Match]
Name=eth0
[Network]
Address=10.148.238.125/30
IPForward=yes
DHCPServer=yes
[DHCPServer]
DNS=84.200.69.80 84.200.70.40
EOF

rpi ~# cat > /etc/systemd/network/08-wlan0.network <<EOF
[Match]
Name=wlan0
[Network]
DHCP=yes
EOF

With the used netmask /30 for eth0 we have selected a very small subnet just for two devices:

Network:   10.148.238.124/30
Broadcast: 10.148.238.127
HostMin:   10.148.238.125
HostMax:   10.148.238.126
Hosts/Net: 2 (Private Internet)

We have to use NAT because it is not practicable to configure the hostspot for routing. To configure NAT we have to extend the wpa_supplicant service with:

rpi ~# systemctl edit wpa_supplicant@wlan0.service

In the empty editor insert these statements, save them and quit the editor:

[Service]
ExecStartPre=/sbin/iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE
ExecStopPost=/sbin/iptables -t nat -D POSTROUTING -o wlan0 -j MASQUERADE

Reboot.
That's it.

Use proxy arp

If you want a workaround for bridging the two interfaces wlan0 and eth0 you can use proxy arp. The setup is a bit more complex and need some additional helpers. How to setup this you can look at the Workaround for a wifi bridge on a Raspberry Pi with proxy arp.

Use an access point

If you also want to use an access point I suggest to configure a routed client connection together with it and a bridge for the access point with the wired connection to the laptop. This would be a general solution for your question. You can connect to any remote hostspot as station and use the local access point from the RasPi as repeater for other wifi devices. The laptop is connected by wire to the same subnet (broadcast domain) spawned by the access point. If the remote hotspot provides an internet access then all local devices incl. the laptop can use this resource. How to setup it you can look at Access point as WiFi repeater, optional with bridge, section Setup bridge.

Ingo
  • 40,606
  • 15
  • 76
  • 189
  • Thanks for your informative article!I will read it back thoroughly and give feedback soon. But for my primary purpose I want use RPi Zero W as an USB NIC, and this will let all 802.11 configuration interface be exposured to my USB Host(laptop). – esky-sh service Apr 29 '19 at 02:46
  • I have a question regard section "Use proxy arp". If i understood correctly, my laptop with ethernet connect to RPi will not get a valid IP address until Wifi connection of RPi completed? That will make RPI 'unvisitable' to my laptop, as IP address as assigned by remote DHCP server accorssing wifi. – esky-sh service May 04 '19 at 03:55
  • @esky-shservice Regarding *proxy arp*: yes, the laptop will get part of the wifi subnet of the remote wifi hotspot like as it is direct connected to it. As part of the subnet it can also connect to the RasPi. – Ingo May 04 '19 at 07:55
  • "As part of the subnet it can also connect to the RasPi." Precisely should be revised to "As part of the subnet it can also connect to the RasPi, when Wifi connection exists."? – esky-sh service May 04 '19 at 08:48
  • Actually I am stuck on that--I can not config wifi connections on RPi, from my laptop, until a wifi connection to AP been built. But RPi wifi connections wont work if I can not login and config wifi setting on RPI. May I need another i/f to connect to RPi, other than usb link in between? It wont be that issue, if I can install a wifi NIC on my laptop as an USB wifi dongle. – esky-sh service May 04 '19 at 08:56
  • @esky-shservice With proxy arp **wlan0** get an ip address from the hotspot. If it isn't connected to it then the RasPi has no ip address and cannot be reached. Fiddling with network connections if you are only headless is a general problem. You always risk to loose connection. I suggest to use at least an USB to serial adapter for the debug console https://raspberrypi.stackexchange.com/a/95562/79866. If you do not want to invest some cents then you can try a headless setup with the routing option. It has a static ip address on **eth0**. – Ingo May 04 '19 at 09:32
  • I have an idea but dont know if it feasible -- Spawn 2 usb ethernet NICs to my laptop. Say usb0 is fixed IP address for communication with RPi and usb1 is in DHCP for exposuring to wifi. All DHCP and ARP packs proxyed between usb1 and wifi on RPi. This will allow my laptop access to RPi no matter whether wifi connected or not. If the propose works, then I can ssh to RPi to make connnection to any wifi APs. – esky-sh service May 04 '19 at 10:59
  • @esky-shservice I do not understand what you want to achieve. Do you want to have two connections to the RasPi, wired and wireless, and it should dynamically switch between both connections, no matter what connection is just active? There is a solution with dynamic failover. But you should make a new question. – Ingo May 13 '19 at 14:10