summaryrefslogtreecommitdiffstats
path: root/etc/inc
diff options
context:
space:
mode:
authorErmal Luçi <eri@pfsense.org>2009-08-14 17:13:38 +0000
committerErmal Luçi <eri@pfsense.org>2009-08-14 17:13:38 +0000
commitf9f71ad37706cbe37ebc8af34aa55c029369c075 (patch)
treedf22e56700dc3b90c6d0f6ed7ded3ecda3f6dd87 /etc/inc
parent74194bf7bb8c8c5783c7a48dfc5f81d4ba5feca7 (diff)
downloadpfsense-f9f71ad37706cbe37ebc8af34aa55c029369c075.zip
pfsense-f9f71ad37706cbe37ebc8af34aa55c029369c075.tar.gz
* Convert captive portal rules to use tables. This reduces the number of rules ALOT.
* Make the peruserbw setting use tables also by taking advantage of the tablearg option. * Convert statistics to use the new improvements of ipfw tables merged previously. * Make the limit of users allowed around 25000 instead of 9999 of before. NOTE: The only thing remaining for full optimization on ipfw(4) side is converting passthrumac and layer2 secure rules to tables aswell.
Diffstat (limited to 'etc/inc')
-rw-r--r--etc/inc/captiveportal.inc184
1 files changed, 88 insertions, 96 deletions
diff --git a/etc/inc/captiveportal.inc b/etc/inc/captiveportal.inc
index bfd3c01..9c70d33 100644
--- a/etc/inc/captiveportal.inc
+++ b/etc/inc/captiveportal.inc
@@ -333,7 +333,7 @@ EOD;
}
$cprules .= <<<EOD
-add 1000 set 1 skipto 1200 all from any to any not layer2
+add 1000 set 1 skipto 1150 all from any to any not layer2
# layer 2: pass ARP
add 1100 set 1 pass layer2 mac-type arp
# pfsense requires for WPA
@@ -350,11 +350,11 @@ add 1100 set 1 pass layer2 mac-type 0x888e
# layer 2: block anything else non-IP
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
+add 1102 set 1 skipto 2000 layer2
EOD;
- $rulenum = 1200;
+ $rulenum = 1150;
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";
@@ -384,23 +384,33 @@ EOD;
$cprules .= "add {$rulenum} set 1 pass tcp from {$cpip} 8001 to any out \n";
}
}
-
$rulenum++;
- $cprules .= <<<EOD
-# ... 10000-19899: rules per authenticated client go here...
+ if (isset($config['captiveportal']['peruserbw'])) {
+ $cprules .= "add {$rulenum} set 2 pipe tablearg ip from table(3) to any in\n";
+ $rulenum++;
+ $cprules .= "add {$rulenum} set 2 pipe tablearg ip from any to table(4) out\n";
+ $rulenum++;
+ } else {
+ $cprules .= "add {$rulenum} set 2 skipto 50000 ip from table(3) to any in\n";
+ $rulenum++;
+ $cprules .= "add {$rulenum} set 2 skipto 50000 ip from any to table(4) out\n";
+ $rulenum++;
+ }
+
+ $cprules .= <<<EOD
# redirect non-authenticated clients to captive portal
-add 19902 set 1 fwd 127.0.0.1,8000 tcp from any to any 80 in
+add 1990 set 1 fwd 127.0.0.1,8000 tcp from any to any 80 in
# let the responses from the captive portal web server back out
-add 19903 set 1 pass tcp from any 80 to any out
+add 1991 set 1 pass tcp from any 80 to any out
# block everything else
-add 19904 set 1 deny all from any to any
+add 1992 set 1 deny all from any to any
-# ... 20000-29899: layer2 block rules per authenticated client go here...
+# ... 2000-49899: layer2 block rules per authenticated client go here...
# pass everything else on layer2
-add 29900 set 1 pass all from any to any layer2
+add 49900 set 1 pass all from any to any layer2
EOD;
@@ -473,7 +483,7 @@ function captiveportal_prune_old() {
$idletimeout = (is_numeric($cpdb[$i][8])) ? $cpdb[$i][8] : $idletimeout;
/* if an idle timeout is specified, get last activity timestamp from ipfw */
if (!$timedout && $idletimeout) {
- $lastact = captiveportal_get_last_activity($cpdb[$i][1]);
+ $lastact = captiveportal_get_last_activity($cpdb[$i][2]);
/* if the user has logged on but not sent any trafic they will never be logged out.
* We "fix" this by setting lastact to the login timestamp
*/
@@ -524,7 +534,8 @@ function captiveportal_prune_old() {
$cpdb[$i][2], // clientip
$cpdb[$i][3], // clientmac
10); // NAS Request
- exec("/sbin/ipfw zero {$cpdb[$i][1]}");
+ exec("/sbin/ipfw table 3 entryzerostats {$cpdb[$i][2]}");
+ exec("/sbin/ipfw table 4 entryzerostats {$cpdb[$i][2]}");
RADIUS_ACCOUNTING_START($cpdb[$i][1], // ruleno
$cpdb[$i][4], // username
$cpdb[$i][5], // sessionid
@@ -596,18 +607,20 @@ function captiveportal_disconnect($dbent, $radiusservers,$term_cause = 1,$stop_t
$stop_time);
}
- mwexec("/sbin/ipfw delete " . $dbent[1] . " " . ($dbent[1]+10000));
-
- /* We need to delete +40500 and +45500 as well...
- * these are the pipe numbers we use to control traffic shaping for each logged in user via captive portal
- * We could get an error if the pipe doesn't exist but everything should still be fine
- */
- if (isset($config['captiveportal']['peruserbw'])) {
- mwexec("/sbin/ipfw pipe " . ($dbent[1]+40500) . " delete");
- mwexec("/sbin/ipfw pipe " . ($dbent[1]+45500) . " delete");
- }
+ mwexec("/sbin/ipfw table 4 delete {$dbent[2]}");
+ mwexec("/sbin/ipfw table 4 delete {$dbent[2]}");
+ mwexec("/sbin/ipfw delete {$dbent[1]}");
+
+ /*
+ * These are the pipe numbers we use to control traffic shaping for each logged in user via captive portal
+ * We could get an error if the pipe doesn't exist but everything should still be fine
+ */
+ if (isset($config['captiveportal']['peruserbw'])) {
+ mwexec("/sbin/ipfw pipe " . ($dbent[1]+20000) . " delete");
+ mwexec("/sbin/ipfw pipe " . ($dbent[1]+20001) . " delete");
+ }
- /* pfSense: ensure all pf states are killed (pfSense) */
+ /* Ensure all pf(4) states are killed. */
mwexec("pfctl -k {$dbent[2]}");
mwexec("pfctl -K {$dbent[2]}");
@@ -713,8 +726,8 @@ function captiveportal_passthrumac_configure($lock = false) {
foreach($config['captiveportal']['passthrumac'] as $ptm) {
/* create the pass through mac entry */
//system("echo /sbin/ipfw add 50 skipto 65535 ip from any to any MAC {$ptm['mac']} any > /tmp/cp");
- mwexec("/sbin/ipfw add 50 skipto 29900 ip from any to any MAC {$ptm['mac']} any keep-state");
- mwexec("/sbin/ipfw add 50 skipto 29900 ip from any to any MAC any {$ptm['mac']} keep-state");
+ mwexec("/sbin/ipfw add 50 skipto 49900 ip from any to any MAC {$ptm['mac']} any keep-state");
+ mwexec("/sbin/ipfw add 50 skipto 49900 ip from any to any MAC any {$ptm['mac']} keep-state");
}
}
@@ -730,34 +743,8 @@ function captiveportal_allowedip_configure() {
/* clear out existing allowed ips, if necessary */
mwexec("/sbin/ipfw table 1 flush");
mwexec("/sbin/ipfw table 2 flush");
- if (file_exists("{$g['vardb_path']}/captiveportal_ip.db")) {
- $ruleno = intval(file_get_contents("{$g['vardb_path']}/captiveportal_ip.db"));
- mwexec("/sbin/ipfw delete {$ruleno}");
- }
if (is_array($config['captiveportal']['allowedip'])) {
-
- $fd = @fopen("{$g['vardb_path']}/captiveportal_ip.db", "w");
- if (!$fd) {
- printf("Error: cannot open allowed ip DB file in captiveportal_allowedip_configure().\n");
- unlock($captiveportallck);
- return 1;
- }
- /* get next ipfw rule number */
- $ruleno = captiveportal_get_next_ipfw_ruleno();
-
- /* if the pool is empty, return apprioriate message and fail */
- if (is_null($ruleno)) {
- printf("Error: system reached maximum login capacity, no free FW rulenos in captiveportal_allowedip_configure().\n");
- fclose($fd);
- unlock($captiveportallck);
- return 1;
- }
- /* Keep the rule number where this will be stored */
- fwrite($fd, $ruleno);
- fclose($fd);
-
- $numberofallowedip = count($config['captiveportal']['allowedip']);
$tableone = false;
$tabletwo = false;
foreach ($config['captiveportal']['allowedip'] as $ipent) {
@@ -771,12 +758,12 @@ function captiveportal_allowedip_configure() {
}
}
if ($tableone == true) {
- mwexec("/sbin/ipfw add $ruleno set 2 skipto 50000 ip from table\(1\) to any in");
- mwexec("/sbin/ipfw add $ruleno set 2 skipto 50000 ip from any to table\(1\) out");
+ mwexec("/sbin/ipfw add 1890 set 2 skipto 50000 ip from table\(1\) to any in");
+ mwexec("/sbin/ipfw add 1891 set 2 skipto 50000 ip from any to table\(1\) out");
}
if ($tabletwo == true) {
- mwexec("/sbin/ipfw add $ruleno set 2 skipto 50000 ip from any to table\(2\) in");
- mwexec("/sbin/ipfw add $ruleno set 2 skipto 50000 ip from table\(2\) to any out");
+ mwexec("/sbin/ipfw add 1892 set 2 skipto 50000 ip from any to table\(2\) in");
+ mwexec("/sbin/ipfw add 1893 set 2 skipto 50000 ip from table\(2\) to any out");
}
}
@@ -784,17 +771,16 @@ function captiveportal_allowedip_configure() {
}
/* get last activity timestamp given ipfw rule number */
-function captiveportal_get_last_activity($ruleno) {
+function captiveportal_get_last_activity($ip) {
$ipfwoutput = "";
- exec("/sbin/ipfw -T list {$ruleno} 2>/dev/null", $ipfwoutput);
-
- /* in */
+ exec("/sbin/ipfw table 3 entrystats {$ip} 2>/dev/null", $ipfwoutput);
+ /* Reading only from one of the tables is enough of approximation. */
if ($ipfwoutput[0]) {
$ri = explode(" ", $ipfwoutput[0]);
- if ($ri[1])
- return $ri[1];
+ if ($ri[4])
+ return $ri[4];
}
return 0;
@@ -969,28 +955,31 @@ function captiveportal_write_elements() {
/*
* This function will calculate the lowest free firewall ruleno
- * within the range specified based on the actual installed rules
+ * within the range specified based on the actual logged on users
*
*/
-function captiveportal_get_next_ipfw_ruleno($rulenos_start = 10000, $rulenos_range_max = 9899) {
-
- $fwrules = "";
- $matches = "";
- exec("/sbin/ipfw show", $fwrules);
- foreach ($fwrules as $fwrule) {
- preg_match("/^(\d+)\s+/", $fwrule, $matches);
- $rulenos_used[] = $matches[1];
- }
- $rulenos_used = array_unique($rulenos_used);
- $rulenos_range = count($rulenos_used);
- if ($rulenos_range > $rulenos_range_max) {
- return NULL;
- }
- $rulenos_pool = range($rulenos_start, ($rulenos_start + $rulenos_range));
- $rulenos_free = array_diff($rulenos_pool, $rulenos_used);
- $ruleno = array_shift($rulenos_free);
+function captiveportal_get_next_ipfw_ruleno($rulenos_start = 2000, $rulenos_range_max = 29899) {
+ global $config, $g;
- return $ruleno;
+ $ruleno = 0;
+ if (file_exists("{$g['vardb_path']}/captiveportal.nextrule"))
+ $ruleno = intval(file_get_contents("{$g['vardb_path']}/captiveportal.nextrule"));
+ else
+ $ruleno = 1;
+ if ($ruleno > 0 && (($rulenos_start + $ruleno) < $rulenos_range_max)) {
+ /*
+ * This allows our traffic shaping pipes to be the in pipe the same as ruleno
+ * and the out pipe ruleno + 1. This removes limitation that where present in
+ * previous version of the peruserbw.
+ */
+ if (isset($config['captiveportal']['peruserbw']))
+ $ruleno += 2;
+ else
+ $ruleno++;
+ file_put_contents("{$g['vardb_path']}/captiveportal.nextrule", $ruleno);
+ return $rulenos_start + $ruleno;
+ }
+ return NULL;
}
/**
@@ -1004,7 +993,7 @@ function captiveportal_get_next_ipfw_ruleno($rulenos_start = 10000, $rulenos_ran
*
*/
-function getVolume($ruleno) {
+function getVolume($ip) {
$volume = array();
@@ -1012,20 +1001,23 @@ function getVolume($ruleno) {
$volume['input_pkts'] = $volume['input_bytes'] = $volume['output_pkts'] = $volume['output_bytes'] = 0 ;
// Ingress
- $ipfw = "";
- $matches = "";
- exec("/sbin/ipfw show {$ruleno}", $ipfw);
- preg_match("/(\d+)\s+(\d+)\s+(\d+)\s+.*/", $ipfw[0], $matches);
- $volume['input_pkts'] = $matches[2];
- $volume['input_bytes'] = $matches[3];
-
- // Flush internal buffer
- unset($matches);
-
- // Outgress
- preg_match("/(\d+)\s+(\d+)\s+(\d+)\s+.*/", $ipfw[1], $matches);
- $volume['output_pkts'] = $matches[2];
- $volume['output_bytes'] = $matches[3];
+ $ipfwin = "";
+ $ipfwout = "";
+ $matchesin = "";
+ $matchesout = "";
+ exec("/sbin/ipfw table 3 entrystats {$ip}", $ipfwin);
+ if ($ipfwin[0]) {
+ $ipfwin = split(" ", $ipfwin[0]);
+ $volume['input_pkts'] = $ipfwin[2];
+ $volume['input_bytes'] = $ipfwin[3];
+ }
+
+ exec("/sbin/ipfw table 4 entrystats {$ip}", $ipfwout);
+ if ($ipfwout[0]) {
+ $ipfwout = split(" ", $ipfwout[0]);
+ $volume['output_pkts'] = $ipfwout[2];
+ $volume['output_bytes'] = $ipfwout[3];
+ }
return $volume;
}
OpenPOWER on IntegriCloud