Skip to content

Instantly share code, notes, and snippets.

@FlorianHeigl
Last active November 28, 2024 22:16
Show Gist options
  • Save FlorianHeigl/d127ec26266f3d4fd95193f432fbc1ae to your computer and use it in GitHub Desktop.
Save FlorianHeigl/d127ec26266f3d4fd95193f432fbc1ae to your computer and use it in GitHub Desktop.
bavarian wifi
# dont execute hook if dhcp req failed
if [ $1 != 0 ]; then
return 0
fi
# get bayernwlan interface name
interface=$( ifconfig | grep -B1 "BAYERNWLAN" | grep -v description: | awk -F: '{print $1}' )
# some validation might be [a-z]+[0-9]
# get bayernwlan interface address
ip=$( ifconfig vtnet2 | grep -w inet | awk '{print $2}' )
# some validation might be a classic ip address regex
# make sure the resulting vars are passed on
export ip interface
# trigger api request
/usr/local/bin/by.py
#!/usr/bin/python3
# Logs into BayernWLAN automatically
# Created on Alpine Linux - I'll make a prod grade version for use on pfSense clusters.
# Likely this is also a nice workaround for OSX clients where the login button is broken all the time.
# Source: https://github.com/asdil12/wifi_autologin/blob/master/wifi_autologin/networks/bayernwlan.py
# Source: https://gist.githubusercontent.com/alexhorn/f1a7f32430e79f835b7dbc180b9ee727/raw/584ba5b79ffc20b9674cabcaded9c9f33c733193/login.py
# Extended to bind to the correct nic ip address when POST'ing to the captive portal
import os
import requests
from requests_toolbelt.adapters import source
ip = os.environ.get('ip')
interface = os.environ.get('interface')
print("will bind to ip %s of %s and try to login to bayernwlan" % (ip, interface))
# per $1 reingeben und als linkup script nehmen
source = source.SourceAddressAdapter(ip)
with requests.Session() as session:
session.mount('https://', source)
sid = session.get('https://hotspot.vodafone.de/api/v4/session').json()['session']
r = session.post('https://hotspot.vodafone.de/api/v4/login?sessionID=%s&action=redirect&portal=bayern' % sid, data={
'loginProfile': '6',
'accessType': 'termsOnly',
'session': sid})
if r.ok:
print("got positive confirmation from portal")
else:
print(r.text)
#!/usr/bin/env bash
# do we need to create a hardlink to post-renew also?
if [[ ${interface} = "wlan0" ]]; then
/usr/local/bin/by.py ${ip}
fi
/etc/udhcpc # ./post-renew
will bind to ip 100.xx.xx.xx of wlan0 and try to login to bayernwlan
got positive confirmation from portal
@FlorianHeigl
Copy link
Author

FlorianHeigl commented Nov 28, 2024

caveats

  • you need to use the dhcp-assigned dns server to do the lookup of hotspot.vodafone.com or it will go to a central server where it's not entitled to a session (403)
  • when testing with curl, not all libcurl versions allow you to set a specific dns interface

@FlorianHeigl
Copy link
Author

FlorianHeigl commented Nov 28, 2024

for pfSense I recommend going with the dhcp exit hook as shown here.

reason:

  • there's nothing in pfSense shell land that provides useful access to the information we need.
  • doing it this way has no need for interaction with the whole firewall stack
  • error handling is wrapped in dhclient and it will tell us if it didn't have luck getting a lease
  • we can even report back to dhclient if we managed to unlock access
  • we can rely on the "overwrite dns with dhcp one" which in reality just adds this dns as primary, so we're not exposed to a large amount of problems on that end. we can fall back to google dns etc. for the firewalls local resolution. client resolution can be kept separate.

it'll be a very easy spot if you want to replace the python stack with something else, i.e. these

bash
freifunk-openwrt
travelmate

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment