Captive portal manual logout page address
-
I had a different approach:
- host override in dns forwarder : logout.me -> 1.1.1.1
- modify capture of 1.1.1.1 in ipfw : it gets always redirected, even if authenticated
- user gets a cookie with session id.
- modify index.php to check if redirection url is http://logout.me and check session cookie (you have to auth again to logout if you close the browser but not just the popup.)
p.s.1 If I'm not wrong in your solution if I spoof my IP/mac I could logout other people by accessing your logout php.
p.s.2 yes, I know: I should use https captive portal because others my intercept my session logout cookie..
-
Thanks for the ideas and security issue.
Your right, I added to /usr/local/captiveportal/index.php (end of the file):
} else if (already_connected($clientip, $clientmac)) { /* display already connected page - offer logout */ portal_reply_page($redirurl, "already_connected",null,$clientmac,$clientip); } else /* display captive portal page */ portal_reply_page($redirurl, "login",null,$clientmac,$clientip); ob_flush(); ?>
In /etc/inc/captiveportal.inc:
... function already_connected($clientip, $clientmac) { global $cpzone; if (($clientip != "") && ($clientmac != "")) { $query = "WHERE ip = '{$clientip}' AND mac = '{$clientmac}'"; $cpdb = captiveportal_read_db($query); /* Lookup the $sessionid */ foreach ($cpdb as $cpentry) { if (($cpentry[2] == $clientip) && ($cpentry[3] == $clientmac)) return $cpentry[5]; } return false; } else return false; } ...
- user gets a cookie with session id.
This means a cookie will be communicated to the browser when the portal clients succeeds authentication ?
edit: btw, from where did you send the cookie ? From /etc/inc/captiveportal.inc : end of function portal_allow() ?
If so, when:
@lsense:- modify index.php to check if redirection url is http://logout.me and check session cookie (you have to auth again to logout if you close the browser but not just the popup.)
then correct, the session gets reused!
@/etc/inc/captiveportal.inc:CONCURRENT LOGIN - REUSING OLD SESSION
No need to do what my function function already_connected($clientip, $clientmac) does !
Good idea ! I'll implement that.p.s.1 If I'm not wrong in your solution if I spoof my IP/mac I could logout other people by accessing your logout php.
Yes, true.
The impostor and real client will be thrown of the portal. Authentication will be needed to regain access again.
Normally, if the impostor has the IP and MAC, other troubles will happen ;)p.s.2 yes, I know: I should use https captive portal because others my intercept my session logout cookie..
I use a (free) certificate from startssl for more then a year now. Just to protect the login sequences. I didn't had much feedback from portal clients who had login problems.
-
Gertjan very good ideas and thanks for the detailed descriptions,
I would really like to have a chance to see your complete implementation, because it seems much simpler and well integrated than mine.
A further question: is it possible to ask the developers to include such a functionality in a pfsense future release?
Looking in the forum it will be very appreciated!
Thanks and regards
-
My files, right now:
Upload these two files with the FileManager available in the Captive Portal:
style.css - http://pastebin.com/LqLx9G5f
already-connected.html - http://pastebin.com/p8GRpuHQThese two file will be available in /var/db/cpelements as:
captiveportal-style.css
captiveportal-already-connected.htmlModify these files:
Te entire file: /usr/local/captiveportal/index.php - http://pastebin.com/jgDrEvpP/etc/inc/captiveportal.php :
Replace the function portal_reply_page(…) for this one http://pastebin.com/mUzp4q3gJust above this new function portal_reply_page(...), add this new function already_connected(...) - http://pastebin.com/emQgMQp8
How it work:
At the very end of /usr/local/captiveportal/index.php - if the visitor isn't logged in yet, the login page will be show (line 237 : /* display captive portal page */).
Just before, this test is added:} else if (already_connected($clientip, $clientmac)) { /* display already connected page - offer logout */ portal_reply_page($redirurl, "already_connected",null,$clientmac,$clientip)
The test uses $clientip and $clientmac, which should be known at that moment.
already_connected($clientip, $clientmac) is the function that you added to /etc/inc/captiveportal.php, and looks up the users $sessionid in captive portal logged in user database.
It should return a $sessionid.
If it does, then portal_reply_page(…) is being called with a new parameter, like this:
portal_reply_page($redirurl, "already_connected",null,$clientmac,$clientip).I modified portal_reply_page(..) somewhat so it can handle the new "already_connected".
portal_reply_page(..) will, again, lookup the users $sessionid and then include our logout page:$htmltext = get_include_contents("{$g['captiveportal_path']}/captiveportal-already-connected.html");
(this is the file you uploaded with the filemanager).
Note: below, in portal_reply_page(..), I added these:
$htmltext = str_replace("\$PORTAL_SESSION\$", htmlspecialchars($sessionid), $htmltext);
and
$htmltext = str_replace("#PORTAL_SESSION#", htmlspecialchars($sessionid), $htmltext);
this was for debugging issues.
What I didn't test:
I use https portal login - I didn't test http login (I guess it should work).I can't implement right now is what lsense did: when the user logs in, send over a persistent (encoded) cookie with the visitors IP, MAC and session ID. This way, things could be more safe and easy to implement. (Portal visitors should accept cookies if they want t logout, of course …)
But, right now, these variables are send over my secured https connection (my logout page is SSL secured).I mentionned in my login page, this one {$g['varetc_path']}/captiveportal_{$cpzone}.html" :
You can disconnect yourself. To do so, visit this page again: [#PORTAL_ACTION#](#PORTAL_ACTION#) Click on the link to open it already in a new window Note: I only use the local User Manager, build in pfSense. I haven't test other login possibilities like Radius, Pass-through credits allowed per MAC address and Vouchers. I will test the last two as soon as I have some time. Pass-through MAC Auto Entry has its own 'logout' possibility. PS: I copied files and functions from my running portal pfsense box. It 'should' work. Be ready, thought, to debug if needed. Keep safe copies of the files you modify: /usr/local/captiveportal/index.php /etc/inc/captiveportal.php
-
This means a cookie will be communicated to the browser when the portal clients succeeds authentication ?
edit: btw, from where did you send the cookie ? From /etc/inc/captiveportal.inc : end of function portal_allow() ?
If so, when:
@lsense:- modify index.php to check if redirection url is http://logout.me and check session cookie (you have to auth again to logout if you close the browser but not just the popup.)
then correct, the session gets reused!
I set logout cookie in /etc/inc/captiveportal.inc function portal_allow() as simply as:
/* set logout cookie */ setcookie("logout", $sessionid);
then in /usr/local/captiveportal/index.php:
... else if ($redirurl == 'http://logout.me/') { if (isset($_COOKIE["logout"])) { $logoutcookie = $_COOKIE["logout"]; setcookie("logout", "", time() - 3600); echo << <eod<br><title>Disconnected</title> **Disconnected.** EOD; captiveportal_disconnect_client($logoutcookie); } else { captiveportal_logportalauth('failed, missing cookie: reauth',$clientmac,$clientip,"LOGOUT"); portal_reply_page($redirurl, "login",null,$clientmac,$clientip); } }</eod<br>
-
As lsesne proposes, I have it working with cookies now.
No more IP and MAC posting.Note: If portal visitor doesn't like cookies (read: he won't be doing much on the Internet) the discussed logging method won't work.
edit: lol: I was just posting the above when lsesne posted.
I created and destroyed the cookie in the same places !!I destroyed like this:
-
Here are my modifications that work with cookies:
Modify these files:
The entire file: /usr/local/captiveportal/index.php : http://pastebin.com/yJirfya6 (includes latest updates from https://github.com/pfsense/pfsense/commit/1b244d3828e83d3c1677d88d5c6bfcb34debac83 )/etc/inc/captiveportal.php :
-
Replace the entire function portal_reply_page(…) with this one : http://pastebin.com/wjWXea06
-
Just above this new function portal_reply_page(…), add this new function already_connected(…) : http://pastebin.com/x3fxwEf8
-
Replace the entire function portal_allow(…) with this one : http://pastebin.com/ivzjTuns
And:
Upload these two files with the FileManager available in the Captive Portal:
style.css - http://pastebin.com/LqLx9G5f
already-connected.html - http://pastebin.com/p8GRpuHQ -
-
Here are my modifications that work with cookies:
Modify these files:
The entire file: /usr/local/captiveportal/index.php : http://pastebin.com/yJirfya6 (includes latest updates from https://github.com/pfsense/pfsense/commit/1b244d3828e83d3c1677d88d5c6bfcb34debac83 )/etc/inc/captiveportal.php :
-
Replace the entire function portal_reply_page(…) with this one : http://pastebin.com/wjWXea06
-
Just above this new function portal_reply_page(…), add this new function already_connected(…) : http://pastebin.com/x3fxwEf8
-
Replace the entire function portal_allow(…) with this one : http://pastebin.com/ivzjTuns
And:
Upload these two files with the FileManager available in the Captive Portal:
style.css - http://pastebin.com/LqLx9G5f
already-connected.html - http://pastebin.com/p8GRpuHQAny new updates on pastebin? it seems that pastebin has already removed the entries…
-
-
Sorry.
…. I've updated to the latest pfSense without any 'copies' of the modified files mentioned above.
:(
-
Here are my modifications that work with cookies:
Please note : I use the https version of the captive portal with a valid (startssl.com certificat) (I don't know if this is important).
Right now, (January 2015) this setup works on one of my pfSense installations (an hotel).
I'm using a nearly clean, original "2.1.5-RELEASE (amd64) built on Mon Aug 25 07:44:45 EDT 2014".edit: these pastebin.org files are locked 'forever' - keep in mind that used to work with 2.1.5 - They might need some re-coding for 2.2.
File: /usr/local/captiveportal/index.php : http://pastebin.com/scYuKTyw - index.php - compare and modify last ~ 15 lines
Basically, this parted gets inserted:} else if ((isset($_COOKIE['cookie_portal']) && already_connected($_COOKIE['cookie_portal']))) /* if we have a valid session, display already connected page - offer logout */ portal_reply_page($redirurl, "already_connected",null,$clientmac,$clientip);
File /etc/inc/captiveportal.php :
-
Replace the entire function portal_reply_page(…) with this one : http://pastebin.com/piamkhNB
-
Just above this new function portal_reply_page(...), add this new function already_connected(…) : http://pastebin.com/CFatytZ9
-
Replace the entire function portal_allow(…) with this one : http://pastebin.com/jDHVaNwf (actually, I just added nearly at the bottom one line:
setcookie("cookie_portal", $sessionid);
And:
Upload these two files with the FileManager available in the Captive Portal:
style.css - http://pastebin.com/MqwEcxVP (this file will be called and used as captiveportal-style.css when uploaded)
xxxxxxx-already-connected.html - http://pastebin.com/PUyQvAuv (this file will be called and used as "captiveportal-xxxxxxx-already-connected.html" when uploaded)You probably have to change the first part of the last file name = "xxxxxxx" in xxxxxxx-already-connected.html
Edit your instance (zone) of your captive portal. You will find the wanted parted in the URL:
Example, mine is showing this:
http://192.168.1.1/services_captiveportal.php?zone=xxxxxxx
(Note: my first and unique Captive portal zone is being called "ZONE1" - that's NOT the part we wanted)Btw: @lsense, if you are there:
- host override in dns forwarder : logout.me -> 1.1.1.1
Ok, done.
- modify capture of 1.1.1.1 in ipfw : it gets always redirected, even if authenticated
Could you detail this please ? What is de ipfw rule ? Injected where ?
-
-
So i cant get this to work. I do get a cookie on the devices but i do not get redirected to the logout page.
My index.php looks like this:
} else if ($_POST['accept'] && $clientip && $cpcfg['auth_method'] == "none") {
captiveportal_logportalauth("unauthenticated",$clientmac,$clientip,"ACCEPT");
portal_allow($clientip, $clientmac, "unauthenticated");} else if (already_connected($clientip, $clientmac)) {
/* display already connected page - offer logout */
portal_reply_page($redirurl, "already_connected",null,$clientmac,$clientip);} else
/* display captive portal page */
portal_reply_page($redirurl, "login",null,$clientmac,$clientip);ob_flush();
?>
Any ideas?
-
I detailed this index.php - by putting the whole file on pastbin.com
File: /usr/local/captiveportal/index.php : http://pastebin.com/scYuKTyw - index.php
Just replace the one you have right now.
Be careful : 2.1.5 only !!
edit have it also working on 2.2 now. -
Thanks for your reply. I see that I missed the part for checking for a cookie (my php skills are kinda low).
I'll try this tommorow on a 2.1.5 box.
If I may ask you another question: where do you put your " cookie destroy" code.
-
….
If I may ask you another question: where do you put your " cookie destroy" code.I don't :) (I stopped doing so).
If you want to destroy it, have a look at the index.php
Look for this line:captiveportal_disconnect_client($_POST['logout_id']);
$_POST['logout_id']
will be the $session_id.
Just before that line, if you like, you can destroy your cookie. edit: wrong ! had to put that code higher up - before the 'logged-out-windows' is being send - see line 121-124 in index.php : http://pastebin.com/scYuKTyw
Or do what lsense proposed here : https://forum.pfsense.org/index.php?topic=77143.msg422179#msg422179But, what happens if you don't ?
Ones disconnected, the session Id will be 'non-existent' (its a big random number).
So, it can't be reused to re-disconnect, neither disconnect some one else (remember: you have to have the same IP and same sessions Id to interact with a session from some one else).
Anyway, to access the disconnect function, you have to have a valid session first.As said before: I use a https portal login page - with a real certificate (a valid one, guaranteed by StartSSL) - so sniffing the initial login from some one else isn't an easy thing to do.
Important : if you want to debug this kind of stuff, do not use 'echo' all over the place, use this function:
captiveportal_logportalauth($text1,$text2,$text3, $text4);
Have a loot at http://pastebin.com/jDHVaNwf to see examples how t use it.
Just drop some captiveportal_logportalauth($text1,$text2,$text3, $text4); on strategic places to see what is getting reached when.
-
Thanks GertJan, got it working now :)
-
I'll give it a try to 'backport' all this to pfSense 2.2 Release.
I'm pretty sure its possible. -
Got it working on 2.2. Just do the same thing :)
-
Got it working on 2.2. Just do the same thing :)
Yep. You're right. Works for me on 2.2 now.
I'll have to do some checking the next severals days - have 'verbose portal logging' activate to see how it goes. -
Hi there,
I am not able to get it working after days effort. I am not using https CP.
Can anyone please write a step by step guide to make this working.
Thanks
Regards
amitaussie
-
I never tried it without https login.
Like: "why do it the easy way, if the difficult way is available ?" :)
https need valid signed certificates by a know authority, I just followed "PFsense 2.1 MultiCP and https with Windows Radius Guide" (in this forum) and …. it worked - costs me some time and zero € or $ **.I'll test the plain http tomorrow morning (can't test my portal on distance >:( )
**) but you need to have a valid, existing domain name on the internet, which, of course, costs some € or $ a year ......
Btw: Here are my portal stats (all stats are pfSense internals) http://www.test-domaine.fr/munin/brit-hotel-fumel.net/pfsense.brit-hotel-fumel.net/index.html#portalusers