Turning My SailfishOS Phone into a WiFi Hotspot with VPN Sharing
This blog post explains how I turned my SailfishOS phone into a WiFi hotspot that shares its internet and even a VPN connection with other devices. I go over how wpa_supplicant manages WiFi, how I set up a second WiFi interface, and how I built a custom DHCP server to assign IP addresses. In the end, I not only got my hotspot working but also discovered a way to route VPN traffic through it, making it even more useful for remote work and travel.
Configuring WiFi Repeating on SailfishOS
Why I Did This
As a digital nomad, I needed a way to share my phone’s WiFi connection with other devices while also routing all traffic through a VPN. More importantly, I wanted to ensure my employer wouldn't detect that I had left North America. This led me to experiment with creating a functional WiFi access point on SailfishOS that could share both internet and VPN connectivity.
Understanding the Role of wpa_supplicant
SailfishOS, like many Linux-based systems, uses wpa_supplicant
to manage WiFi connections. Running the following command:
ps aux | grep "wpa_supp"
reveals that wpa_supplicant
starts at boot with the following process:
/usr/sbin/wpa_supplicant -u -c /etc/wpa_supplicant/wpa_supplicant.conf -O/var/run/wpa_supplicant -u -P /var/run/wpa_supplicant.pid
This process is crucial for enabling background scanning (bgscan
), which allows the device to search for available WiFi networks while remaining connected.
Creating a Second Virtual WiFi Interface
To enable WiFi repeating, I had to stop the default wpa_supplicant
process and launch two separate instances: one for maintaining the original WiFi connection (wlan0
) and another for creating a new access point (wlan1
).
# Kill the existing wpa_supplicant process
pkill wpa_supplicant
# Create a new access point (wlan1)
/usr/sbin/wpa_supplicant -B -c /tmp/wpa_supplicant_ap.conf -O /var/run/wpa_supplicant -i wlan1
# Restart the original WiFi connection (wlan0)
/usr/sbin/wpa_supplicant -B -u -c /etc/wpa_supplicant/wpa_supplicant.conf -O/var/run/wpa_supplicant -u -P /var/run/wpa_supplicant.pid -i wlan0
At this point, my SailfishOS device successfully created an access point (test_ap
), while still maintaining an internet connection through wlan0
. I was able to see test_ap
on other devices, but they failed to obtain an IP address.
Catching A Lucky Break
During testing, devices failed to obtain an IP address from the access point. However, manually assigning an IP address (e.g., 10.10.0.1
) to a client device somehow worked, allowing internet access. This suggests that the WiFi driver is handling most of the complex networking under the hood. It seems that simply bringing up test_ap
and connecting to the internet was a fortunate success rather than an expected outcome. This finding guided my approach to implementing a DHCP server.
Implementing a Custom DHCP Server for wlan1
I opted for a Python-based DHCP server to dynamically assign IP addresses to devices connecting to wlan1
. This allows for better customization and control over IP leases. The following example implementation demonstrates how a DHCP server can be structured in Python, but my real implementation is available on my GitHub repository.
Setting Up the Python DHCP Server
I wrote a lightweight DHCP server in Python that listens on wlan1
and assigns IP addresses dynamically:
import socket
import struct
def dhcp_server():
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind("", 67) # Listen on port 67 (DHCP requests)
while True:
data, addr = sock.recvfrom(1024)
print(f"Received DHCP request from {addr}")
response = struct.pack("!BBBB", 2, 1, 6, 0) # DHCP OFFER
sock.sendto(response, addr)
if __name__ == "__main__":
dhcp_server()
This script provides a basic DHCP response, but my actual implementation includes additional logic for assigning IPs properly. The full version of my DHCP server is available on my GitHub.
Assigning a Static IP to wlan1
Before starting the DHCP server, I assigned a static IP to wlan1
to act as the gateway:
ifconfig wlan1 192.168.27.1 up
This ensures that connected devices know where to send traffic.
Setting Up Network Routing
To forward traffic from wlan1
to wlan0
, I enabled IP forwarding and set up NAT:
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE
This configuration allowed devices connected to test_ap
to access the internet via wlan0
.
Taking Things One Step Further - VPN Repeating via Wifi
While experimenting with this setup, I identified a way to share my active VPN connection with test_ap
. I can loop through existing interfaces, even the virtual interfaces created by vpn software, and apply the MASQUERADE rules.
# Print the interfaces
echo "Matching Interfaces:"
for iface in $INTERFACES; do
echo "$iface"
done
# Loop through interfaces and apply MASQUERADE
echo "Applying MASQUERADE rules:"
for iface in $INTERFACES; do
echo "Adding NAT rule for interface: $iface"
iptables -t nat -A POSTROUTING -s 10.10.0.0/16 -o "$iface" -j MASQUERADE
done
Using Qcommand
To make this setup actually practicle, i recommend to use QCommand. You can use QCommand to create a UI button that launches your hotspot script without needing to type commands manually. After installing QCommand from OpenRepos, follow these steps:
- Open QCommand and create a new command entry.
- Name it something like "Start Hotspot".
- In the command field, enter the full path to your script, e.g.,
/home/nemo/start_hotspot.sh
- Save the entry and test it by tapping on it.
This way, you can enable your WiFi access point with a single tap from the QCommand UI!
Final Thoughts
After extensive testing, my SailfishOS phone is now acting as a fully functional WiFi repeater! Using a custom Python DHCP server, I gained more control over IP assignments and network behavior. This marks a significant breakthrough in enabling WiFi repeating on SailfishOS.
I have documented my progress in a Github [1]repository and welcome contributions from anyone interested in helping fine-tune the setup!