WiFi sharing on iOS

Tunneling network traffic from a laptop to an iOS device: escaping crowded radio bands, internet over USB, MAC whitelisting circumvention and more.

WiFi sharing on iOS

On my (old) laptop I have a wireless network adapter (Qualcomm Atheros QCA9565 / AR9565) that only support 2.4 GHz WiFi. Apart from the slower speeds, a problem arises when trying to establish a connection in crowded spaces over the 2.4 GHz band since this frequency band is usually more crowded and offers less available channels. In the university library the situation is so bad that the laptop struggles to make a connection and keep jumping from one access point to another making WiFi unusable.

Since the iPad has 5 GHz connectivity, I wanted to share its connection with the laptop. With the following setup we will be able to share the network connection of the iPad (WiFi, cellular, VPN) with the laptop. This guide works for any iOS device, including the iPhone.

Arch on iOS & Port Forwarding

We need to use UTM, which is an application that allows to run virtual machines on iOS. Check out my guide to find out how to install it.

iOS App SideLoading
Sideloading on iOS with SideStore: an untethered, community driven alternative app store for non-jailbroken iOS devices.

Once installed and started, in UTM install ArchLinux (or any other linux-based distro). In the virtual machine (VM) settings (in UTM select the VM and tap the settings icon on the top left) go to the Network section and forward at least two ports: :22 → :2222 for connecting via SSH and :8080 → :8080 for the tunnel we will setup. This process exposes the internal VM ports (22 and 8080) to the iPad network (ports 2222 and 8080). This allows any device connected on the same network to reach the VM over those ports. You can test this on your home WiFi by trying to SSH into the VM on port 2222.

Since we will not be relaying on WiFi to connect to the iPad, we want to forward the two ports to the laptop over a USB connection. This can be done using libusbmuxd which provides the iproxy utility.

GitHub - libimobiledevice/libusbmuxd: A client library to multiplex connections from and to iOS devices
A client library to multiplex connections from and to iOS devices - GitHub - libimobiledevice/libusbmuxd: A client library to multiplex connections from and to iOS devices

With iproxy we can forward the SSH port. Start the VM, connect the iPad to the computer with USB and forward the SSH port. The left side is the laptop port, the right one is the port on the iPad. In this case the command is iproxy 2222:2222. Once iproxy is listening, try connecting with SSH (ssh [email protected] -p2222 uname -a). On a successful connection the proxy connection looks like this:

$ iproxy 2222:2222
Creating listening port 2222 for device port 2222
waiting for connection
New connection for 2222->2222, fd = 5
waiting for connection
Requesting connecion to USB device handle 1 (serial: 00001234-0123456789ABCDEF), port 2222

Using SSH we can share a network connection by creating a socks5 proxy:

ssh [email protected] -p2222 -D 1337 -N -n

This command create a socks5 proxy to which we can connect on the laptop on port 1337 (for example using SwitchyOmega). This allows internet access but it's relatively slow due to SSH overhead. A better approach is to use socat to create a tunnel.

Tunneling with socat


We will now use socat to create a tunnel between the VM and the laptop. To do so we first need to generate two key pairs and place them on the proper device.

#!/bin/bash
function generate_cert()
{
 openssl genrsa -out $1.key 1024
 openssl req -new -key $1.key -x509 -days 365 -out $1.crt
 cat $1.key $1.crt > $1.pem
 chmod 600 $1.key $1.pem
}

# Generate iPad/iPhone certificate
generate_cert socat_ios

# Generate laptop certificate
generate_cert socat_laptop

On the iPad run the following commands to configure the NAT and the firewall:

set EXT enp0s1
set INT tun0

sudo iptables -t nat -A POSTROUTING -o $EXT -j MASQUERADE
sudo iptables -A FORWARD -i $EXT -o $INT -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i $INT -o $EXT -j ACCEPT

sudo sysctl -w net.ipv4.ip_forward=1

AI/LLM explanation of the previous commands


The commands you have provided are used to configure a NAT (Network Address Translation) router. NAT is a technique that allows multiple devices on a local network to share a single public IP address. This is useful for home networks, where there are typically more devices than there are public IP addresses available.

The first two commands, set EXT enp0s1 and set INT tun0, define the external and internal interfaces of the router. The external interface is the interface that is connected to the public internet, while the internal interface is the interface that is connected to the local network.

The next three commands, sudo iptables -t nat -A POSTROUTING -o $EXT -j MASQUERADE, sudo iptables -A FORWARD -i $EXT -o $INT -m state --state RELATED,ESTABLISHED -j ACCEPT, and sudo iptables -A FORWARD -i $INT -o $EXT -j ACCEPT, configure the firewall on the router. The first command, sudo iptables -t nat -A POSTROUTING -o $EXT -j MASQUERADE, enables NAT on the router. The second command, sudo iptables -A FORWARD -i $EXT -o $INT -m state --state RELATED,ESTABLISHED -j ACCEPT, allows traffic from the external interface to the internal interface, as long as the traffic is related to an existing connection. The third command, sudo iptables -A FORWARD -i $INT -o $EXT -j ACCEPT, allows traffic from the internal interface to the external interface.

The final command, sudo sysctl -w net.ipv4.ip_forward=1, enables IP forwarding on the router. IP forwarding is necessary for NAT to work.

Once these commands have been executed, the router will be able to translate the private IP addresses of the devices on the local network to the public IP address of the router. This will allow the devices on the local network to access the internet, even though they do not have their own public IP addresses.

And open the tunnel with

sudo socat -d -d OPENSSL-LISTEN:8080,bind=0.0.0.0,cert=socat_ios.pem,cafile=socat_laptop.crt,reuseaddr,fork TUN:10.23.23.1/24,up

On the laptop start the proxy connection

iproxy 8080:8080

and open the other end of the tunnel:

sudo socat -d -d OPENSSL:127.0.0.1:8080,cert=socat_laptop.pem,cafile=socat_ios.crt TUN:10.23.23.2/24,iff-up=1

You should now see a message of successful connection printed by iproxy as well as connection information printed by both socat commands.

To redirect all laptop traffic through the tunnel:

sudo ip route add default via 10.23.23.1

You should now be able to reach the internet (ping 1.1.1.1) via the iPad.

The connection speed depends on the type of USB cable that you use, for example I used a USB 2.0 cable (USB A to C) which ended up limiting the bitrate to around 280 Mbit/s. You can test it using iperf3.

Use Cases

Basically all the network traffic of the laptop goes through the iPad, so to the upstream internet provider sees only the iPad as connected. Benefits and example includes

  • 2.4 GHz band too crowded and no 5 GHz hardware on laptop
  • VPN sharing: e.g. Google One VPN is not available for linux or sometimes the number of simultaneously connected devices is limited
  • MAC address whitelist circumvention: e.g. only the iPad's MAC is allowed to connect
  • Advanced WiFi security connections bypass: e.g. TSL, TTLS ecc

Resources

Poor man’s SSL-VPN with socat
Online repository of technical notes, tutorials, how-to’s, memos, scripts about various technical topics and tasks.
How to forward traffic using iptables rules?
I am new to iptables and I have been doing Google searches for a few days now without finding a good solution to this problem. I have computer A with a public ip address (say 192.0.2.1) that can a...