Hello! there may be a way to configure the access point so it always resolve to a specific domain. On the config.json your hostname will generate a local URL (mdns) (e.g. your-hostname.local) exposing port 80. So that would enable your users to connect to that URL once connected to the access point WiFi and get all the instructions about how to connect. Having said that, it would resolve to a local IP (potentially different for every access point) not a static IP address.
Hi @mpous,
Thanks for your answer. I’ve heard about the .local
domains, but it’s not really what I’m trying to accomplish. I’d like to browse to, for example: access-point.mydomain.com
, and when connected to the AP, it resolves to its own IP address (so 10.42.0.1
for example). I know this can be done by using dnsmasq
, but running my own dnsmasq
instance in a container adds some more maintenance and probably another container. But because the HostOS already uses it, it’d be better if I can configure that dnsmasq
instance from within my container.
I’ve followed Connecting the device to a wifi behind a captive, and the DBus is enabled. But if I understand @majorz, I can’t really use that dnsmasq
instance, which is too bad. But please correct me if I’m wrong
Hey, if I’m understanding the query correctly I think that the extra_hosts
parameter should help?
Hi,
It’s not from within my container that I’d like to set access-point.mydomain.com
to a specific host, but from the client that’s connected to the AP created by my balena device. So I’ve to use some DNS service like dnsmasq
probably. But thanks for the link!
Ah, my mistake. Yes it does sound like dnsmasq
would help here.
Hi,
I don’t know what you mean by ‘this’ exactly. The DNS service or the whole updatable access point?
I’m happy to share some details about my access point application .
Sorry for the ambiguity
Most critically for me, when a client is connected to the WiFi access point, how to route their request to some.domain.com
to a localhost:port
destination running inside balenaOS.
No problem!
When my wlan0 is initiated as an access point (because it can’t connect to a Wi-Fi network), it also starts a dnsmasq
instance in the background (spawn
in Node.js) with the following config parameters (credits to wifi-connect)
dnsmasq \
--address=/#/10.42.0.1 \
--dhcp-range=10.42.0.1,10.42.0.254 \
--dhcp-option=option:router,10.42.0.1 \
--interface=wlan0 \
--keep-in-foreground \
--bind-interfaces \
--except-interface=lo \
--conf-file \
--no-hosts \
--log-facility=-
Change device, gateway, route and dhcp according to your needs.
But what this does is the following:
It routes everything to 10.42.0.1
. You can’t forward it to a port, because when a user does an HTTP request, it uses port 80, so DNSMASQ routes it to 10.42.0.1:80
. HTTPS is the same, it routes to 10.42.0.1:443
. So you can’t change the port, only the address (I’d recommend to just use this ports for your web application, because it’s the standard).
It also only binds to wlan0, so your ethernet can still be connected to the internet for example.
Because everything routes to 10.42.0.1
, most devices will show a ‘hotspot’ interface, because it can’t reach it’s hotspot check (e.g. Apple checks for http://captive.apple.com/hotspot-detect.html).
When wlan0 is connected to a Wi-Fi client, or is trying to connect, my app kills the dnsmasq instance and tries to connect via NetworkManager. When it fails, it sets up the AP again and thus dnsmasq. But when it’s successful, it stays a Wi-Fi client.
Good to know
Most HTTPS websites set a HSTS-header. This means that your browser will “always” know, that when connecting to, for example, https://google.com, it uses HTTPS with a (valid) certificate. So when you’re connected to the AP, and you’re trying to go to https://google.com (with your webserver listening on port 443), it’ll give an HTTPS error, because the certificate is invalid (it’s not the Google certificate it expected).
We’re working around that by using a subdomain (local.domain.com
) which doesn’t use HTTPS but just HTTP. That’ll work because the HSTS-header is not set for that domain. So we instruct users to connect to the AP, and if the hotspot interface doesn’t come up, go to local.domain.com
, and it’ll “redirect” them to 10.42.0.1
.
Hope you get the idea, if you’ve any other questions, please ask them here!
I’ve got this working by using Google and open-source projects, so I’m happy to share some knowledge!
Thanks bversluijs, very helpful. Combining that with some info above…
/mnt/boot/system-connections/balena-hotspot
[connection]
id=balena-hotspot
uuid=36060c57-aebd-4ccf-aba4-ef75121b5f77
type=wifi
autoconnect=true
interface-name=wlan0
permissions=
secondaries=
[wifi]
band=bg
mac-address-blacklist=
mac-address-randomization=0
mode=ap
seen-bssids=
ssid=MY_HOTSPOT_SSID
[wifi-security]
group=
key-mgmt=wpa-psk
pairwise=
proto=rsn
psk=MY_HOTSPOT_PASSWORD
[ipv4]
dns-search=
method=shared
[ipv6]
addr-gen-mode=stable-privacy
dns-search=
method=auto
docker-compose.yaml
version: "2.1"
services:
dnsmasq:
build: ./dnsmasq
container_name: dnsmasq
restart: always
network_mode: host
entrypoint:
- sh
- ./start.sh
cap_add:
- NET_ADMIN
Dockerfile
FROM balenalib/debian:stretch
RUN apt-get update
RUN apt-get install -y dnsmasq
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
COPY dnsmasq.conf /etc/dnsmasq.conf
COPY start.sh start.sh
start.sh
echo "Starting dnsmasq - $(date)"
dnsmasq \
--address=/#/10.42.0.1 \
--dhcp-range=10.42.0.1,10.42.0.254 \
--dhcp-option=option:router,10.42.0.1 \
--interface=wlan0 \
--keep-in-foreground \
--bind-interfaces \
--except-interface=lo \
--conf-file \
--no-hosts \
--log-facility=-
tail -f /dev/null
Some issues
When the entrypoint initialises, it says:
dnsmasq: unknown interface wlan0
Running nmcli
on balena root suggests this does indeed exist. Maybe an execution order issue…
# nmcli
wlan0: connected to balena-hotspot
"Ralink n"
wifi (rt2800usb), 9C:EF:D5:FB:C1:D4, hw, mtu 1500
inet4 10.42.0.1/24
route4 10.42.0.0/24
inet6 fe80::4da7:5750:80d8:2c99/64
route6 fe80::/64
route6 ff00::/8
...
If I run the dnsmasq command again it will says:
dnsmasq: failed to create listening socket for 10.42.0.1: Address already in use
In any case, its not quite working. Visiting a domain, eg) thing.local
does not route to localhost:80
on the balena device.
I have tried changing the [ipv4]
hotspot settings to method=manual
but if I do that, the hotspot does not seem to be initialised (I can’t see it on my client device).
Any ideas what the issue may be?
EDIT:
I have been able to make it work by delaying the dnsmasq command a few seconds to avoid unknown interface wlan0
and also changing the IPV4 config:
[ipv4]
address1=10.42.0.1/24
dns=127.0.0.1;1.1.1.1;
dns-search=
method=manual
Thanks for your help!
Hi,
Settings the method to manual and adding address1=10.42.0.1/24
should be enough indeed.
Glad you could make it work!
Hi, me again ,
For the security of the access point, I’m using the following:
[wifi-security]
group=
key-mgmt=wpa-psk
pairwise=
proto=rsn
psk=MY_HOTSPOT_PASSWORD
However, when I connect to it via my iPhone or Mac, it says that the security is weak (probably WPA1/WPA2 (TKIP)), but the most secure at the moment (afaik) is WPA2 (AES). I’ve read that proto=rsn
means it can use WPA2, but doesn’t force it.
Is there a way to force WPA2 (AES)? I’ve read the NetworkManager documentation about this, and it’s probably the pairwise
or group
setting, because that can be set to ccmp
, which is AES(?). But I want it to remain stable and working on most devices, so that’s why I wanted to ask this first.
Thanks in advance!
I’ve added the following:
group=ccmp;
pairwise=ccmp;
This removes the warning on my Apple devices that it’s insecure. However, I’m still curious if this is the best / most stable solution.