Captive Portal behind Router or different subnet

  • Hi guys,

    Need help on above issue. I manage to make Captive Portal to works for user having different subnet from Pfsense interface but I can't make the logout button and redirect to work. For ur reference my basic setup is like below:

    Internet == Pfsense ==  Router  == User

    where router to user =

    pfsense to router =

    Need to know whether this setup is possible to be done with pfsense. Thanks.

  • Hi sekult,

    I banged my head against this issue for quite a while. I found that in a flat network (where the client ip was on the same subnet as the LAN interface) everything worked fine, but when we changed our network topology to use vlans (and vlan routing), pfsense decided that it would remap requests to the pfsense box to use the ip address of the requested external site. While this works for login purposes (I guess there is some kind of ip masq going on), it fails epically for the the logout button (because by the time the user clicks on the logout button, the ip-masq is no longer in place, so the request tries to go to the actual external site ip.

    Trawling through the code (in /etc/inc/, I found references to portal_ip_from_client_ip(), which tries to match the client ip to one of the pfsense interface ips. But because your client ip does not match any of the interface ips, it fails.

    I found that commenting out the guts of this function, leaving only "return false;" worked for me. In this case, the code that calls portal_ip_from_client_ip(), uses the host name of the pfsense box. (for me this is 'pfsense').

    function portal_ip_from_client_ip($cliip) {
            global $config;
            $interfaces = explode(",", $config['captiveportal']['interface']);
            foreach ($interfaces as $cpif) {
                    $ip = get_interface_ip($cpif);
                    $sn = get_interface_subnet($cpif);
                    if (ip_in_subnet($cliip, "{$ip}/{$sn}"))
                            return $ip;
            // doesn't match up to any particular interface
            // so let's set the portal IP to what PHP says
            // the server IP issuing the request is.
            // allows same behavior as 1.2.x where IP isn't
            // in the subnet of any CP interface (static routes, etc.)
            // rather than forcing to DNS hostname resolution
            $ip = $_SERVER['SERVER_ADDR'];
            if (is_ipaddr($ip))
                    return $ip;
            return false;

    At this point, the login/logout pages are accessed from http://pfsense:8000/  and worked fine.

    Note: I assume that you have solved the routing and firewall issues, ie;

    Added Gateway (for your LAN interface) in System | Routing | Gateways
    Added Route (to your client subnet, via your LAN interface) in System | Routing | Routes
    Added Firewall Rule (same as for "Default allow LAN to any rule", but changing 'LAN net' to your client subnet/mask)  in Firewall | Rules | LAN

    Hope this helps.


Log in to reply