diff options
author | Ermal Luçi <eri@pfsense.org> | 2009-05-21 21:44:38 +0000 |
---|---|---|
committer | Ermal Luçi <eri@pfsense.org> | 2009-05-21 21:44:58 +0000 |
commit | f8b1131038f1a8ced102c79ed6c72ef9dc05e6f1 (patch) | |
tree | af5965311271a555f903685cbb586a40aed64ff9 | |
parent | 868a5b990ab32dbea625c254a6daa264086fd08b (diff) | |
download | pfsense-f8b1131038f1a8ced102c79ed6c72ef9dc05e6f1.zip pfsense-f8b1131038f1a8ced102c79ed6c72ef9dc05e6f1.tar.gz |
Make CP multi-interface capable.
-rw-r--r-- | etc/inc/captiveportal.inc | 132 | ||||
-rw-r--r-- | etc/inc/interfaces.inc | 4 | ||||
-rw-r--r-- | etc/inc/util.inc | 3 | ||||
-rwxr-xr-x | usr/local/captiveportal/index.php | 31 | ||||
-rwxr-xr-x | usr/local/www/services_captiveportal.php | 10 |
5 files changed, 121 insertions, 59 deletions
diff --git a/etc/inc/captiveportal.inc b/etc/inc/captiveportal.inc index 0093495..ef793e7 100644 --- a/etc/inc/captiveportal.inc +++ b/etc/inc/captiveportal.inc @@ -47,10 +47,32 @@ function captiveportal_configure() { global $config, $g; $captiveportallck = lock('captiveportal'); + + $cpactive = false; + if (isset($config['captiveportal']['enable'])) { + $cpips = array(); + $ifaces = get_configured_interface_list(); + $cpinterfaces = explode(",", $config['captiveportal']['interface']); + $firsttime = 0; + foreach ($cpinterfaces as $cpifgrp) { + if (!isset($ifaces[$cpifgrp])) + continue; + if ($firsttime > 0) + $cpinterface .= " or "; + $firsttime = 1; + $tmpif = get_real_interface($cpifgrp); + if (!empty($tmpif)) { + $cpinterface .= "via {$tmpif}"; + $cpips[] = get_interface_ip($cpifgrp); + } + } + if (count($cpips) > 0) { + $cpactive = true; + $cpinterface = "{ {$cpinterface} } "; + } + } - if (isset($config['captiveportal']['enable']) && - (($config['captiveportal']['interface'] == "lan") || - isset($config['interfaces'][$config['captiveportal']['interface']]['enable']))) { + if ($cpactive == true) { if ($g['booting']) echo "Starting captive portal... "; @@ -69,7 +91,7 @@ function captiveportal_configure() { mwexec("/sbin/kldload dummynet"); /* generate ipfw rules */ - $cprules = captiveportal_rules_generate(); + $cprules = captiveportal_rules_generate($cpinterface, $cpips); /* stop accounting on all clients */ captiveportal_radius_stop_all(true); @@ -276,17 +298,15 @@ EOD; mwexec("/sbin/kldunload ipfw.ko"); } - unlock($captiveportallck); + unlock($captiveportallck); return 0; } -function captiveportal_rules_generate() { +function captiveportal_rules_generate($cpif, &$cpiparray) { global $config, $g; $cpifn = $config['captiveportal']['interface']; - $cpif = get_real_interface($cpifn); - $cpip = get_interface_ip($cpifn); $lanip = get_interface_ip("lan"); /* note: the captive portal daemon inserts all pass rules for authenticated @@ -301,27 +321,27 @@ function captiveportal_rules_generate() { /* if list */ $iflist = get_configured_interface_list(); foreach ($iflist as $ifent => $ifname) { - if($cpifn == $ifname) + if(stristr($cpifn, $ifname)) continue; $int = get_real_interface($ifname); $cprules .= "add 30 set 1 skipto 50000 all from any to any in via {$int} keep-state\n"; } /* captive portal on LAN interface? */ - if ($cpifn == "lan") { + if (stristr($cpifn, "lan")) { /* add anti-lockout rules */ $cprules .= <<<EOD -add 500 set 1 pass all from $cpip to any out via $cpif -add 501 set 1 pass all from any to $cpip in via $cpif +add 500 set 1 pass all from $lanip to any out $cpif +add 501 set 1 pass all from any to $lanip in $cpif EOD; } $cprules .= <<<EOD # skip to traffic shaper if not on captive portal interface -add 1000 set 1 skipto 50000 all from any to any not layer2 not via $cpif +add 1000 set 1 skipto 50000 all from any to any not layer2 not $cpif # pass all layer2 traffic on other interfaces -add 1001 set 1 pass layer2 not via $cpif +add 1001 set 1 pass layer2 not $cpif # layer 2: pass ARP add 1100 set 1 pass layer2 mac-type arp @@ -341,39 +361,50 @@ add 1101 set 1 deny layer2 not mac-type ip # layer 2: check if MAC addresses of authenticated clients are correct add 1102 set 1 skipto 20000 layer2 -# allow access to our DHCP server (which needs to be able to ping clients as well) -add 1200 set 1 pass udp from any 68 to 255.255.255.255 67 in -add 1201 set 1 pass udp from any 68 to $cpip 67 in -add 1202 set 1 pass udp from $cpip 67 to any 68 out -add 1203 set 1 pass icmp from $cpip to any out icmptype 8 -add 1204 set 1 pass icmp from any to $cpip in icmptype 0 - -# allow access to our DNS forwarder -add 1300 set 1 pass udp from any to $cpip 53 in -add 1301 set 1 pass udp from $cpip 53 to any out - -# allow access to our DNS forwarder if it incorrectly resolves the hostname to $lanip -add 1300 set 1 pass udp from any to $lanip 53 in -add 1301 set 1 pass udp from $lanip 53 to any out - -# allow access to our web server -add 1302 set 1 pass tcp from any to $cpip 8000 in -add 1303 set 1 pass tcp from $cpip 8000 to any out - -# allow access to lan web server incase the dns name resolves incorrectly to $lanip -add 1302 set 1 pass tcp from any to $lanip 8000 in -add 1303 set 1 pass tcp from $lanip 8000 to any out - EOD; - if (isset($config['captiveportal']['httpslogin'])) { - $cprules .= <<<EOD -add 1304 set 1 pass tcp from any to $cpip 8001 in -add 1305 set 1 pass tcp from $cpip 8001 to any out - -EOD; + $rulenum = 1200; + foreach ($cpiparray as $cpip) { + //# allow access to our DHCP server (which needs to be able to ping clients as well) + $cprules .= "add {$rulenum} set 1 pass udp from any 68 to 255.255.255.255 67 in \n"; + $rulenum++; + $cprules .= "add {$rulenum} set 1 pass udp from any 68 to {$cpip} 67 in \n"; + $rulenum++; + $cprules .= "add {$rulenum} set 1 pass udp from {$cpip} 67 to any 68 out \n"; + $rulenum++; + $cprules .= "add {$rulenum} set 1 pass icmp from {$cpip} to any out icmptype 8\n"; + $rulenum++; + $cprules .= "add {$rulenum} set 1 pass icmp from any to {$cpip} in icmptype 0 \n"; + $rulenum++; + //# allow access to our DNS forwarder + $cprules .= "add {$rulenum} set 1 pass udp from any to {$cpip} 53 in \n"; + $rulenum++; + $cprules .= "add {$rulenum} set 1 pass udp from {$cpip} 53 to any out \n"; + $rulenum++; + # allow access to our web server + $cprules .= "add {$rulenum} set 1 pass tcp from any to {$cpip} 8000 in \n"; + $rulenum++; + $cprules .= "add {$rulenum} set 1 pass tcp from {$cpip} 8000 to any out \n"; + + if (isset($config['captiveportal']['httpslogin'])) { + $rulenum++; + $cprules .= "add {$rulenum} set 1 pass tcp from any to {$cpip} 8001 in \n"; + $rulenum++; + $cprules .= "add {$rulenum} set 1 pass tcp from {$cpip} 8001 to any out \n"; + } } + $rulenum++; + //# allow access to our DNS forwarder if it incorrectly resolves the hostname to $lanip + $cprules .= "add {$rulenum} set 1 pass udp from any to {$lanip} 53 in \n"; + $rulenum++; + $cprules .= "add {$rulenum} set 1 pass udp from {$lanip} 53 to any out \n"; + //# allow access to lan web server incase the dns name resolves incorrectly to $lanip + $rulenum++; + $cprules .= "add {$rulenum} set 1 pass tcp from any to {$lanip} 8000 in \n"; + $rulenum++; + $cprules .= "add {$rulenum} set 1 pass tcp from {$lanip} 8000 to any out \n"; + $cprules .= <<<EOD # ... 10000-19899: rules per authenticated client go here... @@ -956,7 +987,6 @@ function captiveportal_write_elements() { * within the range specified based on the actual installed rules * */ - function captiveportal_get_next_ipfw_ruleno($rulenos_start = 10000, $rulenos_range_max = 9899) { $fwrules = ""; @@ -1065,4 +1095,18 @@ function portal_mac_fixed($clientmac) { return FALSE ; } +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; + } + + return false; +} + ?> diff --git a/etc/inc/interfaces.inc b/etc/inc/interfaces.inc index 3ec42a3..8e65a1d 100644 --- a/etc/inc/interfaces.inc +++ b/etc/inc/interfaces.inc @@ -2184,9 +2184,9 @@ function get_real_interface($interface = "wan") { function guess_interface_from_ip($ipaddress) { $ret = `/usr/bin/netstat -rn | /usr/bin/awk '/^{$ipaddress}/ {print \$6}'`; - if(empty($ret)) { + if (empty($ret)) return false; - } + return $ret; } diff --git a/etc/inc/util.inc b/etc/inc/util.inc index b318f92..c419369 100644 --- a/etc/inc/util.inc +++ b/etc/inc/util.inc @@ -732,7 +732,6 @@ function verify_digital_signature($fname) { global $g; return mwexec("/usr/local/sbin/gzsig verify {$g['etc_path']}/pubkey.pem < " . escapeshellarg($fname)); - } /* obtain MAC address given an IP address by looking at the ARP table */ @@ -967,4 +966,4 @@ function is_interface_mismatch() { return $do_assign; } -?>
\ No newline at end of file +?> diff --git a/usr/local/captiveportal/index.php b/usr/local/captiveportal/index.php index eab9763..3771bf9 100755 --- a/usr/local/captiveportal/index.php +++ b/usr/local/captiveportal/index.php @@ -49,8 +49,13 @@ if (!$clientip) { if (isset($config['captiveportal']['httpslogin'])) $ourhostname = $config['captiveportal']['httpsname'] . ":8001"; -else - $ourhostname = get_interface_ip($config['captiveportal']['interface']) . ":8000"; +else { + $ifip = portal_ip_from_client_ip($clientip); + if (!$ifip) + $ourhostname = $config['system']['hostname'] . ":8000"; + else + $ourhostname = "{$ifip}:8000"; +} if ($orig_host != $ourhostname) { /* the client thinks it's connected to the desired web server, but instead @@ -84,7 +89,7 @@ if (!$clientmac && $macfilter) { /* find out if we need RADIUS + RADIUSMAC or not */ if (file_exists("{$g['vardb_path']}/captiveportal_radius.db")) { $radius_enable = TRUE; - if ($radius_enable && isset($config['captiveportal']['radmac_enable'])) + if (isset($config['captiveportal']['radmac_enable'])) $radmac_enable = TRUE; } @@ -167,8 +172,14 @@ function portal_reply_page($redirurl, $type = null, $message = null, $clientmac /* substitute other variables */ if (isset($config['captiveportal']['httpslogin'])) $htmltext = str_replace("\$PORTAL_ACTION\$", "https://{$config['captiveportal']['httpsname']}:8001/", $htmltext); - else - $htmltext = str_replace("\$PORTAL_ACTION\$", "http://" . get_interface_ip($config['captiveportal']['interface']) . ":8000/", $htmltext); + else { + $ifip = portal_ip_from_client_ip($clientip); + if (!$ifip) + $ourhostname = $config['system']['hostname'] . ":8000"; + else + $ourhostname = "{$ifip}:8000"; + $htmltext = str_replace("\$PORTAL_ACTION\$", "http://{$ourhostname}/", $htmltext); + } $htmltext = str_replace("\$PORTAL_REDIRURL\$", htmlspecialchars($redirurl), $htmltext); $htmltext = str_replace("\$PORTAL_MESSAGE\$", htmlspecialchars($message), $htmltext); @@ -320,8 +331,14 @@ function portal_allow($clientip,$clientmac,$username,$password = null, $attribut if (isset($config['captiveportal']['httpslogin'])) $logouturl = "https://{$config['captiveportal']['httpsname']}:8001/"; - else - $logouturl = "http://" . get_interface_ip($config['captiveportal']['interface']) . ":8000/"; + else { + $ifip = portal_ip_from_client_ip($clientip); + if (!$ifip) + $ourhostname = $config['system']['hostname'] . ":8000"; + else + $ourhostname = "{$ifip}:8000"; + $logouturl = "http://{$ourhostname}/"; + } echo <<<EOD <HTML> diff --git a/usr/local/www/services_captiveportal.php b/usr/local/www/services_captiveportal.php index 7d5a73d..bc07fb2 100755 --- a/usr/local/www/services_captiveportal.php +++ b/usr/local/www/services_captiveportal.php @@ -149,7 +149,7 @@ if ($_POST) { } if (!$input_errors) { - $config['captiveportal']['interface'] = $_POST['cinterface']; + $config['captiveportal']['interface'] = implode(",", $_POST['cinterface']); $config['captiveportal']['maxproc'] = $_POST['maxproc']; $config['captiveportal']['maxprocperip'] = $_POST['maxprocperip'] ? $_POST['maxprocperip'] : false; $config['captiveportal']['timeout'] = $_POST['timeout']; @@ -194,6 +194,8 @@ if ($_POST) { $retval = captiveportal_configure(); $savemsg = get_std_save_message($retval); + + $pconfig['cinterface'] = implode(",", $_POST['cinterface']); } } include("head.inc"); @@ -276,16 +278,16 @@ function enable_change(enable_change) { <tr> <td width="22%" valign="top" class="vncellreq">Interface</td> <td width="78%" class="vtable"> - <select name="cinterface" class="formselect" id="cinterface"> + <select name="cinterface[]" multiple="true" size="3" class="formselect" id="cinterface"> <?php $interfaces = get_configured_interface_with_descr(); foreach ($interfaces as $iface => $ifacename): ?> - <option value="<?=$iface;?>" <?php if ($iface == $pconfig['cinterface']) echo "selected"; ?>> + <option value="<?=$iface;?>" <?php if (stristr($pconfig['cinterface'], $iface)) echo "selected"; ?>> <?=htmlspecialchars($ifacename);?> </option> <?php endforeach; ?> </select> <br> - <span class="vexpl">Choose which interface to run the captive portal on.</span></td> + <span class="vexpl">Choose which interface(s) to run the captive portal on.</span></td> </tr> <tr> <td valign="top" class="vncell">Maximum concurrent connections</td> |