captive portal is not working on mobiles
-
@Gertjan
All I can tell you is that I estimate that this site, that I set up 15 years ago, on pfSense sees about 200 devices connected at any single time over a 6 month seasonal period in a year. People and devices are constantly coming and going so there is a wide range of opportunity to see many different configurations. There are a wide variety of countries represented as well, increasing the device diversity. It has a mix of every type of authentication method, including freeRadius, vouchers and Local Database. In 2021, perhaps 1 in 10 devices would have issues and took a power cycling to correct 50% of the time. In 2022 I implemented my first use of DHCP114 but the example from Apple had some missing quotes in it and it took most of the season for me to figure that out as we still had random failures to connect. Android was less trouble but still had occasional issues. Let's remember that iOS was still mastering their side as well and each iOS release changed the symptoms a bit. By the end of 2022, the sample I recently provided here was complete and we did not have a single login issue during the 2023 season, mostly under 23.05/2.7.0. In fact there is no one dedicated to support Captive Portal on site at all. I consider DHCP 114 to be an essential contributor to that improvement. It is not all that complex to implement. The fact Kea DHCP doesn't yet support options is the next hurdle to get across but I am optimistic that this is a long term fix. We have other, massive, captive portal issues with data quotas, time quotas, multiuser data/time tracking and Vlan Tunnel support for freeRadius and we use custom software mods to fix all those successfully. Redmines have been raised (locked onto "NEXT" so never coming?) but the one for the freeRadius Vlan Tunnel support was outright cancelled so I expect it will be a very long time before the Captive Portal works for us without customization. The fact we have to customize captive portal forced us to downgrade from plus to 2.7.0 going forward to reduce the frequency of having to update our code to the latest version of pfSense. We are currently on 2.7.2 after experiencing an offseason data crash that seems eerily similar to the published ZFS file system issue.At least we feel the login issue is behind us and I thought others might benefit as well so I posted here.
-
@Gertjan said in captive portal is not working on mobiles:
Why would I even try ?
The OS 'any OS) will throw out a "connection test" http request (not https !).
For example, my iPhone uses : "http%3A%2F%2Fcaptive.apple.com%2Fhotspot-detect.html" (you find it in on the Status > System Logs > System > GUI Service page).If the page shows up with a known answer (= "Success "), the device will know it has a direct internet connection, and every thing stops there.
Ok, true, all it knows is that http requests (TCP to port 80) work - and because captive.apple.com resolved, DNS also work).If nothing or something else comes back, the OS fires up a web browser (a scaled down version of Safari in Apple's case) - or your default system browser ion other devices wit the same ( ! ) http://captive.apple.com/hotspot-detect.html URL.
In an attempt to answer this and explain why I prefer the DHCP 114 approach along with explaining what I believe may be happening:
- It takes time for everything to process, wait for a response, check to see if it says "Success", timeouts and sometimes the word "Success" is so small on the temp browser screen that users can't see it at all, thinking the connection process has hung. There is also a delay before the connection screen clears the "orange" No Internet Connection prompt. End users can miss all this and simply try to connect again.
- Another issue I encountered is that the same URL can resolve to multiple IPs over time on many sites. The pre-fetch on the Resolver can have a different, wrong IP address and that can cause issues. This is true for pass through URLs on the Captive Portal as well.
- The assumption that the device connection test always goes to the same URL is incorrect. There are dozens or hundreds of different URLs that are checked. I found that was one of the reasons for it being intermittent, especially if it couldn't be resolved through the portal. I found it retries different sites randomly to attempt to verify connectivity if routing to the first one is down. You are relying on this fixed URL to launch the rule for redirect to captive portal login as well so if it checks a different one, it fails to launch the login screen. And then there is android and all the other operating systems out there.
- Using DHCP custom option114 was created and promoted by Apple but adopted industry wide and will work immediately every time. No need for the firewall rules or delays in letting the "OLD" system of checking for "Success" to work. I must admit that there can still be a delay after captive portal authentication when iOS checks again for connectivity but it is a delay in removing the "No Internet Connection" display, the connectivity itself is instantaneous and I often see an email arrive before the Apple device removes that warning.
I think you may have more patience than some and often it is just the user of the device not understanding they are connected or not current in their device updates. If DHCP 114 fails, the system you rely on is still there as a "Backup" and that fact is what made debugging it so time consuming.
The universal nature of using DHCP option 114 is faster and more reliable than the "assumptions" and delays built into the rules bases setup you describe.
-
Also look at: https://datatracker.ietf.org/doc/rfc8910/ for info on DHCP 114 specs
-
To make this discussion complete and to provide a diagnostic process to test if Captive Portal is working in response to this topic itself:
@Gertjan said in captive portal is not working on mobiles:
"Because of the web server's redirection instructions,
and pfSense 'pf' firewall rues ( see /tmp/rules.debug) the https request will get redirected to
http://192.168.2.1:8002/...... if you've chosen http login, or
https://portal.yourlocaldomain.tld:8003/ if you have chosen https login."- The reason the device sends an http:// URL to captive portal, after failing to receive a "Success" response, rather than an https:// URL to the captive portal is because the captive portal can redirect http:// simply because it is not encrypted. Any https:// URL would not be intercepted because the captive portal/firewall would not be able to decode it into a url to recognize/resolve and redirect to the login page. One exception is the https://portal.yourlocaldomain.tld:8003/.... URL of the login screen itself as it does not need to be redirected at all.
- Likewise, the reason http://neverssl.com will still work in a device browser and will almost always launch the login screen is because it can be decoded and redirected by the captive portal/rules to the captive portal login page. This is not always true of the temp browser launched by the operating system of the device, iOS for eg, it may require a secure login. In that case, close the temp browser, open another browser like safari, and enter http://neverssl.com and it will launch the login screen if captive portal is set up correctly.
The most reliable fix is to "forget" the wifi station and then reconnect to the Access Point. Most often that corrects the login issue. If it does not, then exiting the temp browser, "Done, use without internet" option or just bailing out, and using something like Safari or Chrome with a url of http://neverssl.com, or other http:// URL, will launch the login screen and captive portal can then activate the session. If it does not, then captive portal setup may be incomplete.
In my experience, this is less likely to happen if iOS has access to valid DHCP option 114 data. This can happen even if you are using DHCP 114 because bailing out of the login screen without responding can confuse iOS and Captive Portal if the wifi connection remains intact.
-
@EDaleH said in captive portal is not working on mobiles:
In an attempt to answer this and explain why I prefer the DHCP 114 approach ...
When I found Apple's suggestion, the proposed RFC solution you've showed above, I knew that that was the way to go.
My thoughts are this : DHCP negotiation telling the device that a portal is present. It knows right from the network connection start what URL to present to the user so he/she can login.
Just perfect. It can be https right away.@EDaleH said in captive portal is not working on mobiles:
check to see if it says "Success", timeouts and sometimes the word "Success" is so small on the temp browser screen that users can't see it at all
The user can't see success ??
The user never should see that word. The test URL is send right after DHCP negotiation, typically by a command line like 'lynx'.
I need two command on a pfSEnse to do this manually :[23.09.1-RELEASE][root@pfSense.bhf.tld]/root: fetch http://captive.apple.com/hotspot-detect.html hotspot-detect.html 69 B 437 kBps 00s [23.09.1-RELEASE][root@pfSense.bhf.tld]/root: cat hotspot-detect.html <HTML><HEAD><TITLE>Success</TITLE></HEAD><BODY>Success</BODY></HTML>
An example on a Debian host :
root@ns311465:~# lynx -dump http://captive.apple.com/hotspot-detect.html Success
@EDaleH said in captive portal is not working on mobiles:
It takes time for everything to process, wait for a response, .... delays ....
I've read (forum) about delays.
My captive portal has 20 max connected users so my 4100 can handle the load quiet easily.
Btw : I've 4 access points in my portal network.@EDaleH said in captive portal is not working on mobiles:
Another issue I encountered is that the same URL can resolve to multiple IPs over time on many sites.
The IP resolved to doesn't matter.
If a portal is present, the http (TCP port 80) request gets redirect to the pfSense portal web server.@EDaleH said in captive portal is not working on mobiles:
The assumption that the device connection test always goes to the same URL is incorrect.
My device, over the year : a a 3G, GS, a 4, 5 7 10 and now iPhone 12, using whatever iOS available during there life span, did.
But, what http test site is used doesn't matter. It should be a http request and that URL should give a known answer back, that's all that counts.@EDaleH said in captive portal is not working on mobiles:
I found that was one of the reasons for it being intermittent, especially if it couldn't be resolved through the portal
That's bad : for a portal to work, DNS should work.
If the device's OS uses a test URL that doesn't exist (isn't resolvable - doesn't have a web server behind it answers "Success" or whatever it should answer) .... well .... then you have a device with a questionable OS. The OS would break captive portal support.
I can image that when you buy a no-brand phone with a cloned android for that device, and the portal detection URL is taken down then for that device portal detection breaks ...
In that case, the issue isn't on my side (the pfSense captive portal), neither the user. "They have what they paid for".
I'm don't want to be that iPhone fan boy, but I never had issues with their devices/OS.@EDaleH said in captive portal is not working on mobiles:
You are relying on this fixed URL to launch the rule for redirect to captive portal login as well so if it checks a different one
Again : the url used isn't hard coded in pfSense. It doesn't care.
No where I've "http://captive.apple.com/hotspot-detect.html" in my pfSense portal settings.
It is hard coded in my phone, that's for sure. Maybe it can fall back to other URLS, I don't know, never saw them.What I've also have seen : Microsoft OS device use a couple of different http URLs.
Android devices users other URL's of course, some are going to a google owned site, some go straight to China .... all depends on the device's OS version an whatever.@EDaleH said in captive portal is not working on mobiles:
Using DHCP custom option114
It has also a IPv6 DHCP solution !
The pfSense portal is IPv4 only right now. The DHCP solution will add full IPv6 support, something I've tried adding myself several times. It was mission impossible. -
I agree that when nothing goes wrong, the login screen will launch and any http:// URL will launch the login screen. The problem is that the real world user does not know that and they "mess with it".
A successful login screen involves both Captive Portal and the Device, so, let's look at it from the Device's perspective:
One common example: A user lands at your installation with an iPhone and looks around. They find a bunch of captive portals available, Day, Week, Month, Recurring, Data, etc. So they try them and connect to each in turn and when the login launches they seem to be stuck on the screen so they make the only choice they have, (Done or Cancel depending upon if this is the first time or they have been here before) they select either Done which closes the browser and typically iOS displays "No Internet Connection" but not always; or, they select "Cancel" which will prompt them to "Use Other Network" or to "Use Without Internet". In many cases they select to use it without internet. Both Done and "Use Without Internet" have turned off the "Auto Login" feature so the next time they connect to this network, it won't launch the login screen simply because it doesn't check for internet connectivity and thus does not try to access an http:// site, therefore failing to trigger the Captive Portal login page. Now they walk up to the Owner and say, the WiFi is not working and the inexperienced Owner of the facility contacts you and says the Captive Portal is broken. The severity of this varies and the current iOS 17+ has yet again improved and this "self corrects" more often, but it still happens, I just duplicated it on an iPhone 12 iOS 17.2.1 while writing this response. Also of note is that iOS does not always display the "No Internet Connection" warning, (because it is no longer checking?) it often just shows a connection so there is no feedback as to what is wrong. If they try to access a secure site like www.google.com, it will display security messages that make users uncomfortable. Those https:// sites do not trigger the captive portal login page, only an http:// link will. The problem is that as long as that WiFi Station ID is in the "My Networks" list, the Auto Login feature will remain off and there will be no Login page when they connect.
Now this broken Captive Portal/Phone needs to be fixed: What do you do next.
- Launch Safari and go to an http:// site (http://neverssl.com) to see if the captive portal launches the login screen and voila, it does. It also will leave the logout window/tab open in the browser if you need to enable your users to logout. The temp browser on the other hand will display but will close the logout window. when you leave the browser to use the phone.
- Tell them to forget the network and reconnect. This will clear the "Auto Login" setting so they see the login screen one more time. The is the quick and dirty solution to put into your handouts.
- Tell them to turn the "Auto Login" feature back on.
As far as issues with the DNS Resolver, pre-fetch, etc, they tend to affect the end user when they are trying to access secure URLs without authentication through the Captive Portal. This is especially true for payment systems if your login process includes an online payment link that must be redirected to before completing the pfSense login (voucher sent automatically to login screen for eg.). All of those links must get through the firewall to work and they are the IPs that are constantly changing. When an user bails out of the payment system, it produces the same results as bailing out of the temp browser login screen does.
Having iOS display the word "Success" in the temporary browser rather than the login screen occurs less frequently but it is also a symptom of this state of confusion. The redirect URL in Captive Portal may be set to go to the original URL which of course is the http://captive.apple.com...... which will display the "Success" text.
-
-
I had some time during lunch break, and went for it.
Step 1 :
Instead of your "dhcp_cp3.php" I've changed the file name to "rfc8910.php", and cleaned up a bit the file you proposed :<?php require_once("auth.inc"); require_once("util.inc"); require_once("functions.inc"); require_once("captiveportal.inc"); header("Expires: 0"); header("Cache-Control: no-cache, no-store, must-revalidate"); header("Pragma: no-cache"); header("Connection: close"); global $g, $config, $cpzone, $cpzoneid, $cpzoneprefix; $cpzone = strtolower($_REQUEST['zone']); $cpcfg = config_get_path("captiveportal/{$cpzone}"); if (empty($cpcfg)) { log_error("rfc8910 - Submission to captiveportal with unknown parameter zone: " . htmlspecialchars($cpzone)); portal_reply_page($redirurl, "error", gettext("Internal error")); ob_flush(); return; } $cpzoneid = $cpcfg['zoneid']; $clientip = $_SERVER['REMOTE_ADDR']; if (!$clientip) { /* not good - bail out */ log_error("Zone: {$cpzone} - rfc8910 - Captive portal could not determine client's IP address."); $errormsg = gettext("An error occurred. Please check the system logs for more information."); portal_reply_page($redirurl, "error", $errormsg); ob_flush(); return; } $cpsession = captiveportal_isip_logged($clientip); ob_flush(); if (empty($cpsession)) { header("Location: https://portal.bhf.tld:8003/rfc8910-T.json?zone={$cpzone}"); } else { header("Location: https://portal.bhf.tld:8003/rfc8910-F.json?zone={$cpzone}"); } ob_flush(); return; }
edit : a lot more stuff could be removed I guess. As small is beautiful .... but I was impatient, so I used "quick is fine also".
Step 2 :
I've created two more files in the /usr/local/captiveportal/ :[23.09.1-RELEASE][root@pfSense.bhf.tld]/usr/local/captiveportal: cat rfc8910-T.json { "captive": true, "user-portal-url": "https://portal.bhf.tld:8003/index.php?zone=cpzone1" } [23.09.1-RELEASE][root@pfSense.bhf.tld]/usr/local/captiveportal: cat rfc8910-F.json { "captive": false, "user-portal-url": "https://portal.bhf.tld:8003/index.php?zone=cpzone1" }
Step 3 :
Add option "114" to the captive portal network DHCP server - must must be ISC.
I've set custom option value to "https://portal.bhf.tld:8003/rfc8910.php?zone=cpzone1"
And yes, I have the pfsense captive portal web server running with a cert that says it's "portal.bhf.tld". It TLS port is 8003 in my case.
My captive portal zone is called "cpzone1"edit :
I did make a packet capture to inspect the DHCP handshake between captive portal pfSense DHCP server and the iPhone device, and saw that DHCP option 114 was there.Step 4 :
I deleted the Wifi/SSID "known network" from my iPhone.
And connected back to the captive portal.Worked flawlessly....... I guess.
I even have the impression it is faster, the login page shows up faster.So make sure I wasn't seeing things that I wanted to see, not that there ware actually not happening, I edited the the file and added a lot of log lines like this :
if (empty($cpsession)) {
captiveportal_logportalauth("rfc8910", "EMPTY SESSION", $clientip, $cpzone);
} else {
captiveportal_logportalauth("rfc8910", "EXISTING SESSION", $clientip, $cpzone);
}so I could see see what part was reached when under with conditions.
I actually saw that when connecting the iPhone to the captive portal SSID, it made a request for the URL, given to the phone with DHCP +option 114
Then the "rfc18910.php" file gave the phone the "rfc8910-T.json" file which indicated the phone that a portal exists.
So, according to the "rfc8910-T.json" content, it used the "https://portal.bhf.tld:8003/index.php?zone=cpzone1" which showed the login page on te phone..And all this magic worked after some plain copy paste (and some small edits).
Wow .... a RFC defined captive portal.
Thank you @EDaleHMinimal changes are needed - no pfSense scripts files changes are needed.
The bad news : works for iPhones only. Other phones : dono (probably not / later / I don't have an android device .... ).
-
@Gertjan
Excellent, nicely cleaned up.I got the impression it was working with Android but did not check it. We had fewer issues there too but I don't believe Android has the equivalent to "auto_logon=False".
I also think Windows is now recognizing 114 based on how fast it loads.In the midst of this, phone users have gotten better at understanding captive portals as well.
-
@EDaleH said in captive portal is not working on mobiles:
I also think Windows is now recognizing 114 based on how fast it loads.
I've brought my Windows 11 pro laptop in.
I removed from the known Wifi networks my captive portal record - and connected to portal network.
It looks like it totally ignores "DHCP option 114" as is didn't make any request for "rfc8910.php" -
Some progress :
/usr/local/captiveportal/rfc8910.php :
<?php require_once("auth.inc"); require_once("util.inc"); require_once("functions.inc"); require_once("captiveportal.inc"); header("Expires: 0"); header("Cache-Control: no-cache, no-store, must-revalidate"); header("Pragma: no-cache"); header("Connection: close"); global $g, $config, $cpzone, $cpzoneid, $cpzoneprefix; $cpzone = strtolower($_REQUEST['zone']); $cpcfg = config_get_path("captiveportal/{$cpzone}"); if (empty($cpcfg)) { log_error("rfc8910.php - Submission to captiveportal with unknown parameter zone: " . htmlspecialchars($cpzone)); portal_reply_page($redirurl, "error", gettext("Internal error")); ob_flush(); return; } $cpzoneid = $cpcfg['zoneid']; $clientip = $_SERVER['REMOTE_ADDR']; if (!$clientip) { /* not good - bail out */ log_error("Zone: {$cpzone} - rfc8910.php - Captive portal could not determine client's IP address."); $errormsg = gettext("An error occurred. Please check the system logs for more information."); portal_reply_page($redirurl, "error", $errormsg); ob_flush(); return; } $cpsession = captiveportal_isip_logged($clientip); $sessionid = $cpsession['sessionid']; ob_flush(); if (empty($cpsession)) { captiveportal_logportalauth("rfc8910", "EMPTY SESSION", $clientip, $cpzone); $seconds_remaining = $cpcfg['timeout']*60; $json_post = array ( 'captive' => true, 'user-portal-url' => "https://portal.bhf.tld:8003/index.php?zone=$cpzone", 'venue-info-url' => "https://portal.bhf.tld:8003/index.php?zone=$cpzone", 'seconds-remaining' => $seconds_remaining, 'can-extend-session' => true ); echo json_encode($json_post, JSON_PRETTY_PRINT); } else { captiveportal_logportalauth("rfc8910", "EXISTING SESSION", $clientip, $cpzone); $seconds_remaining = (time()-$cpsession['allow_time'])+($cpcfg['timeout']*60); $json_post = array ( 'captive' => false, 'user-portal-url' => "https://portal.bhf.tld:8003/index.php?zone=$cpzone", 'venue-info-url' => "https://portal.bhf.tld:8003/index.php?zone=$cpzone", 'seconds-remaining' => $seconds_remaining, 'can-extend-session' => true ); echo json_encode($json_post, JSON_PRETTY_PRINT); } ob_flush(); return; ?>
edit : for those who never look at logs, you could remove the two lines that start with "captiveportal_logportalauth( ....."
No more need to create/maintain/use the two json files "rfc8910-F.json" and "rfc8910-T.json", as they are now generated by rfc8910.php on the dynamically.
The
'venue-info-url' => "https://portal.bhf.tld:8003/index.php?zone=$cpzone",
will show useful info : tap on the SSID of the portal and something news shows up : and bring you to theURL you've chosen under 'venue-info-url'. I've put in place the same URL as the login page : what will happen is that, if the device is logged in already, the logout page is shown !
( Not that someone will make use of this - as you have to find it first )I'm also adding 'seconds-remaining', not sure the iPhone actually uses it.
Small recap about how to use all this :
Place the file I've shown above (this post) here : /usr/local/cativeportal/rfc8910.php
Then, make sure you use the ISC DHCP (no Kea for now), and add an "DHCP OPTION 114" :
My 'text string' : "https://portal.bhf.tld:8003/rfc8910.php?zone=cpzone1"
Where : "cpzone1" is the name of your captive portal zone.
"portal.bhf.tld" is the host name of your captive portal, which should TLS as it it mandatory.
Define the host name "portal.bhf.tld" as a host override under Services > DNS Resolver > General Settings.Take note : TLS means : you should won (rent) a domain name (otherwise the "captive portal" is not something for you).
And that's it.
From now on, devices that support RFC8910 will play nicely.
As no pfSense core files are edited, it's "upgrade" proof, and easy to put in place in case of a re install.
-
@Gertjan said in captive portal is not working on mobiles:
/usr/local/captiveportal/rfc8910.php
Integrating the json data into the code is cleaner but I would like to point out that every instance/zone of the captive portal needs a unique rfc8910.php file, thus I would name them like this: rfc8901_cp1.php, rfc8901_cp2.php,,, etc. If you were ambitious, you could likely create json data on the fly, changing sub-domain, port and zone info on the fly. The simplicity of separate files appeals to my KISS preferences.
@Gertjan said in captive portal is not working on mobiles:
captiveportal_logportalauth("rfc8910", "EXISTING SESSION", $clientip, $cpzone);
$seconds_remaining = (time()-$cpsession['allow_time'])+($cpcfg['timeout']*60);
$json_post = array (
'captive' => false,
'user-portal-url' => "https://portal.bhf.tld:8003/index.php?zone=$cpzone",
'venue-info-url' => "https://portal.bhf.tld:8003/index.php?zone=$cpzone",
'seconds-remaining' => $seconds_remaining,
'can-extend-session' => trueIncluding all the data supported is likely useful as devices adopt full functionality going forward. I do not use this because multiple connections to a single user does not currently accurately cumulate time or data and the result from the code can be simply wrong. Instead, we use custom code to calculate the time remaining for multiple connections to a single account. In that way we can apply a time/quota limit to the user and it will cumulate across all connections on that user account. As captive portal ends the session on a logout, we do not permit a logout, instead we publish a "dashboard" that shows time and data quota remaining or that user account. As stated above, although this launches (it is actually the logout code) in the temp browser, it immediately disappears when the temp browser closes. All of that only happens on the first connection to that Station ID/zone/Portal. For this reason, we provide the link to the "logout" code in our handout and instead it launches this dashboard of info when they want to check it. On Windows systems, there is no temp browser so the end user can leave this "logout" dashboard tab open and we refresh it's contents every 2.5 minutes.
-
@EDaleH said in captive portal is not working on mobiles:
but I would like to point out that every instance/zone of the captive portal needs a unique rfc8910.php file, thus I would name them like this: rfc8901_cp1.php, rfc8901_cp2.php,,, etc
Lol.
That's why I rewrote my rfc810Look again :
'user-portal-url' => "https://portal.bhf.tld:8003/index.php?zone=$cpzone",
the zone parameter is a variable, and the $cpzone available is extracted from the URL used to access the page (and to get the right portal session, etc).
I the device asks for a status update, the
$seconds_remaining = (time()-$cpsession['allow_time'])+($cpcfg['timeout']*60);
field is recalculated so the device knows that after xx seconds my hard time out will apply.I've just one portal instance, and will be testing with 'two' instances in a near future.
@EDaleH said in captive portal is not working on mobiles:
For this reason, we provide the link to the "logout" code
I've found it on the profile page on my iPhone device :
Clicking (taping) on Open (Ouvrir la page d'acceuil ...) will open the logout page - or whatever 'venue-info-url' points to.
As said earlier, no one will find it there.
Btw : I've added all the known RFC fields, just to see what happens - what is usefull, what is supported, etc.
-
@Gertjan said in captive portal is not working on mobiles:
Look again :
'user-portal-url' => "https://portal.bhf.tld:8003/index.php?zone=$cpzone",
the zone parameter is a variable, and the $cpzone available is extracted from the URL used to access the page (and to get the right portal session, etc).Once you setup your extra portals, I think you will find that the "portal.bhf.tld" is pointing at an IP in DNS that is unique to the DHCP assigned to the first captive portal zone. Port 8003 is the https port for that zone only, it won't work on other zones, they have their own unique ports.
Thus, you will need portal2.bhf.tld pointing at the IP of the DHCP lease for the second zone, say zone2, and captive portal will provide the https login page on 8005, etc for other portals. your "user-portal-url" becomes 'user-portal-url' => "https://portal2.bhf.tld:8005/index.php?zone=$cpzone". You can only leave the zone=$cpzone in place because it will correctly resolve based on the session ID but it will change from zone1 to zone2 for the URL.
We are using 8 portals this way as the Access Points are limited to 8 - 802.1Q Vlans per frequency. with 2.4 and 5 GHz that could also be 16 portals if you separate them by frequency as well.
-
I just had a friend drop by with an Android 14 Samsung phone and did a quick test. It supports DHCP 114 for both the login screen and more important, it supports the Venu option as well. iOS as of 17 still does not support Venu. When you reconnect to an active Captive Portal user account with the Android, it loads the Venu link through a notification, which in our case is a "dashboard" that displays your username, amount of data remaining and time remaining as applicable. This is a huge asset, I hope Apple and Microsoft support it soon! As you pointed out in:
@Gertjan said in captive portal is not working on mobiles:
will show useful info : tap on the SSID of the portal and something news shows up : and bring you to theURL you've chosen under 'venue-info-url'. I've put in place the same URL as the login page : what will happen is that, if the device is logged in already, the logout page is shown !
( Not that someone will make use of this - as you have to find it first )Now they don't have to "find it first".
-
@EDaleH said in captive portal is not working on mobiles:
Once you setup your extra portals, I think you will find that the "portal.bhf.tld" is pointing at an IP in DNS that is unique to the DHCP assigned to the first captive portal zone. Port 8003 is the https port for that zone only, it won't work on other zones, they have their own unique ports.
Thus, you will need portal2.bhf.tld pointing at the IP of the DHCP lease for the second zone, say zone2, and captive portal will provide the https login page on 8005, etc for other portals. your "user-portal-url" becomes 'user-portal-url' => "https://portal2.bhf.tld:8005/index.php?zone=$cpzone". You can only leave the zone=$cpzone in place because it will correctly resolve based on the session ID but it will change from zone1 to zone2 for the URL.
My "portal.bhf.tld" is hard coded in my rfc8190.php above.
It's already gone in the file I'm using right now.
The URL used to access the portal contains the &zone=ZONEINDICATOR parameter.
With that info, server IP (the portal base network) is known, so is the host name, like "portalX.bhf.tld".So everything can be generated on the fly, on demand.
@EDaleH said in captive portal is not working on mobiles:
Android 14 Samsung phone and did a quick test. It supports DHCP 114
Good news.
Apple will probably follow very soon. Maybe the upcoming 17.4 'dev' version, we'll see.
That is, I hope.@EDaleH said in captive portal is not working on mobiles:
iOS as of 17 still does not support Venu
It does, the venu URL is there, see the image in my previous post, but to hidden to be actually usefull for the average wifi (portal) user.
-
@Gertjan said in captive portal is not working on mobiles:
I've found it on the profile page on my iPhone device :
I missed it because I think of that page as the "info" page (but it is a profile) due to the i inside the circle that launches it.
Now that I know where they link it, I think that is easy to add to the handout so thanks for finding it.For others reading this: on Apple iOS, Settings, WiFi, connect to the portal, click the i with the circle around it,
Because of the DHCP option 114 code/data sent, there will now be a section called "Portal" where it will say:
"This network provides a portal webpage at subdomain.domain.com (for example).
This is the venue link uploaded in the json data file by DHCP option 114, but in this discussion we are pointing it at the "custom" page associated with Services, Captive Portal, click pencil to edit your portal, HTML Page Contents, portal page contents.If we usee the captive portal logon page link; if the session is already authenticated/active, captive portal (through index.php) will launch the logout page you upload under Logout page contents section for the captive portal.
In our case, we use that logout page to display user id, remaining time & data quota as applicable. Ours is NOT a popup window.
Windows does leave the logout tab open when you connect but once closed you need the url to get it open again. For windows users, publishing the url in a handout/email is the only way for them to return to the "logout" page. As this is the least common denominator, that published URL will work in a browser tab on Windows, Android and iOS devices so the venue url utility is diminished in terms of usefulness. Individual device users may prefer the Android Notification or iOS info/profile link so it is wise to implement it through DHCP 114 for their convenience.
@Gertjan said in captive portal is not working on mobiles:
My "portal.bhf.tld" is hard coded in my rfc8190.php above.
It's already gone in the file I'm using right now.
The URL used to access the portal contains the &zone=ZONEINDICATOR parameter.
With that info, server IP (the portal base network) is known, so is the host name, like "portalX.bhf.tld".So everything can be generated on the fly, on demand.
I am not sure I agree, hopefully I am not missing something here?
What we know is the IP of the device ($clientip = $_SERVER['REMOTE_ADDR'];), not the URL. Normally Captive Portal generates the url that executes index.php but with DHCP 114, there is no "capture" per-se; captive portal is not yet involved so we would have to connect to the URL directly as if the end user typed it in, rather than the rule based process that captures the http:// port 80 request and then creates that url for us. This means we must construct the login URL in advance of sending the json data file to the device through DHCP option 114 so the device's temporary browser can call it directly on an SSL/TLS port. To construct that URL we need to know:- The subdomain of the certificate: "portal" in your example. We know each portal has a different subdomain so that it can be associated with the unique DHCP pool of the specific captive portal.
- The domain of the certificate: This is typically/likely the same for all captive portals: "bhf.tld" in your example.
- The port this portal is on. Although the rfc8910.php code is trying to resolve the zone, I don't think we can determine which portal it is associated with so here we have to hard code it. 8003 for the first, 8005 for the second, etc, etc.
4 The zone: in this case we can determine that from the $cpcfg array.
All of the above information is (can be) in the URL coded into the DHCP option 114 so I think we should be able to parse the URL that called us and by doing so, make a single, universal, rfc8910.php file. I will look into that and post back here if I succeed. I am still not convinced that a file per captive portal is not easier to administer but a universal solution is better if we look at it from the user community perspective. If we succeed, then it could even become part of the project or a patch.
I also want to point out, to those not using multiple portals yet; that you need a Level 2 switch on OPT1(tagged)/LAN(untagged) that supports the VLans (one fore each captive portal), or separate network cards, to implement multiple captive portals. Each portal is assigned to a separate interface in System, Captive Portal, Portal Name. Once that is done, it is easy to construct (hard code) the URL because pfSense/Captive Portal never intercept the URL, the temporary browser goes directly to executing index.php through the URL provided in the json data file sent by the DHCP option 114 which is executing the suggested rfc8910.php file through the "temporary" browser prior to anything being captive, it is done at the time of assigning the client IP when initially connecting to the network.
-
This post is deleted! -
This post is deleted! -
I modified your rfc8910.php to parse the url passed from the DHCP option 114 string such that it launches the correct login URL for each portal through the json data string without any additional files required. It is universal as long as the string placed in the DHCP option 114 server contains the subdomain.domain.com:port info. I checked it on 6 portals with voucher, user and freeRadius authentication. If keeping things clean is an objective, this approach is a one file solution to all DHCP option 114 RFC8910 syntax for user and venue options.
Note that I commented out the seconds_remaining code as it was throwing an exception on my portals authenticated by freeRadius. I did not debug that further.
-
Note: the Apple example has the json URL links inside double quotes as a string. In the above code that would suggest => "$rfc8910_url", not just => $rfc8910_url. In testing it worked equally well both ways.