diff options
author | Ermal <eri@pfsense.org> | 2010-05-05 19:24:28 +0000 |
---|---|---|
committer | Ermal <eri@pfsense.org> | 2010-05-05 19:26:34 +0000 |
commit | b8ed2a11a038955f833cb6742928534200d831bf (patch) | |
tree | a0653403d98887b805d1e6a5e75e0ff625ebc10d | |
parent | b315e307decf76b0b5fd57488a0ed0f383d700e9 (diff) | |
download | pfsense-b8ed2a11a038955f833cb6742928534200d831bf.zip pfsense-b8ed2a11a038955f833cb6742928534200d831bf.tar.gz |
Implement tcp flags and sloppy state on the GUI.
-rw-r--r-- | etc/inc/filter.inc | 57 | ||||
-rwxr-xr-x | usr/local/www/firewall_rules_edit.php | 84 | ||||
-rwxr-xr-x | usr/local/www/guiconfig.inc | 31 | ||||
-rw-r--r-- | usr/local/www/javascript/firewall_rules_edit/firewall_rules_edit.js | 15 |
4 files changed, 158 insertions, 29 deletions
diff --git a/etc/inc/filter.inc b/etc/inc/filter.inc index 2da8548..e0ed52c 100644 --- a/etc/inc/filter.inc +++ b/etc/inc/filter.inc @@ -1599,9 +1599,29 @@ function filter_generate_user_rule($rule) { if($type == "pass") { if(isset($rule['allowopts'])) $aline['allowopts'] = " allow-opts "; - if( isset($rule['source-track']) or isset($rule['max']) or isset($rule['max-src-nodes']) or isset($rule['max-src-conn']) or isset($rule['max-src-states']) ) - if($rule['protocol'] == "tcp") + + $aline['flags'] = ""; + if($rule['protocol'] == "tcp") { + if (isset($rule['tcpflags_any'])) + $aline['flags'] = "flags any "; + else if (!empty($rule['tcpflags2'])) { + $aline['flags'] = "flags "; + if (!empty($rule['tcpflags1'])) { + $flags1 = explode(",", $rule['tcpflags1']); + foreach ($flags1 as $flag1) + $aline['flags'] .= strtoupper($flag1[0]); + } + $aline['flags'] .= "/"; + if (!empty($rule['tcpflags2'])) { + $flags2 = explode(",", $rule['tcpflags2']); + foreach ($flags2 as $flag2) + $aline['flags'] .= strtoupper($flag2[0]); + } + $aline['flags'] .= " "; + } else $aline['flags'] = "flags S/SA "; + } + /* * # keep state * works with TCP, UDP, and ICMP. @@ -1620,30 +1640,37 @@ function filter_generate_user_rule($rule) { switch($rule['statetype']) { case "none": $noadvoptions = true; - $aline['flags'] = " no state "; + $aline['flags'] .= " no state "; break; case "modulate state": case "synproxy state": if($rule['protocol'] == "tcp") - $aline['flags'] = "{$rule['statetype']} "; + $aline['flags'] .= "{$rule['statetype']} "; + break; + case "sloppy state": + $aline['flags'] .= "keep state "; + $rule['sloppy'] = true; break; default: - $aline['flags'] = "{$rule['statetype']} "; + $aline['flags'] .= "{$rule['statetype']} "; + break; } } else - $aline['flags'] = "keep state "; + $aline['flags'] .= "keep state "; if($noadvoptions == false || $l7_present) - if( isset($rule['source-track']) and $rule['source-track'] <> "" or - isset($rule['max']) and $rule['max'] <> "" or - isset($rule['max-src-nodes']) and $rule['max-src-nodes'] <> "" or - isset($rule['max-src-conn']) and $rule['max-src-conn'] <> "" or - isset($rule['max-src-conn-rate']) and $rule['max-src-conn-rate'] <> "" or - isset($rule['max-src-conn-rates']) and $rule['max-src-conn-rates'] <> "" or - isset($rule['max-src-states']) and $rule['max-src-states'] <> "" or - isset($rule['statetimeout']) and $rule['statetimeout'] <> "" or - $l7_present) { + if( (isset($rule['source-track']) and $rule['source-track'] <> "") or + (isset($rule['max']) and $rule['max'] <> "") or + (isset($rule['max-src-nodes']) and $rule['max-src-nodes'] <> "") or + (isset($rule['max-src-conn']) and $rule['max-src-conn'] <> "") or + (isset($rule['max-src-conn-rate']) and $rule['max-src-conn-rate'] <> "") or + (isset($rule['max-src-conn-rates']) and $rule['max-src-conn-rates'] <> "") or + (isset($rule['max-src-states']) and $rule['max-src-states'] <> "") or + (isset($rule['statetimeout']) and $rule['statetimeout'] <> "") or + isset($rule['sloppy']) or $l7_present) { $aline['flags'] .= "( "; + if (isset($rule['sloppy'])) + $aline['flags'] .= "sloppy "; if(isset($rule['source-track']) and $rule['source-track'] <> "") $aline['flags'] .= "source-track rule "; if(isset($rule['max']) and $rule['max'] <> "") diff --git a/usr/local/www/firewall_rules_edit.php b/usr/local/www/firewall_rules_edit.php index 8bd7e49..0eae393 100755 --- a/usr/local/www/firewall_rules_edit.php +++ b/usr/local/www/firewall_rules_edit.php @@ -121,6 +121,15 @@ if (isset($id) && $a_filter[$id]) { $pconfig['log'] = isset($a_filter[$id]['log']); $pconfig['descr'] = $a_filter[$id]['descr']; + if (isset($a_filter[$id]['tcpflags_any'])) + $pconfig['tcpflags_any'] = true; + else { + if (isset($a_filter[$id]['tcpflags1']) && $a_filter[$id]['tcpflags1'] <> "") + $pconfig['tcpflags1'] = $a_filter[$id]['tcpflags1']; + if (isset($a_filter[$id]['tcpflags2']) && $a_filter[$id]['tcpflags2'] <> "") + $pconfig['tcpflags2'] = $a_filter[$id]['tcpflags2']; + } + if (isset($a_filter[$id]['tag']) && $a_filter[$id]['tag'] <> "") $pconfig['tag'] = $a_filter[$id]['tag']; if (isset($a_filter[$id]['tagged']) && $a_filter[$id]['tagged'] <> "") @@ -359,6 +368,19 @@ if ($_POST) { $input_errors[] = "You can only select a layer7 container for Pass type rules."; } + if (!$_POST['tcpflags_any']) { + $settcpflags = array(); + $outoftcpflags = array(); + foreach ($tcpflags as $tcpflag) { + if ($_POST['tcpflags1_' . $tcpflag] == "on") + $settcpflags[] = $tcpflag; + if ($_POST['tcpflags2_' . $tcpflag] == "on") + $outoftcpflags[] = $tcpflag; + } + if (empty($outoftcpflags) && !empty($settcpflags)) + $input_errors[] = "If you specify TCP flags that should be set you should specify out of which flags as well."; + } + if (!$input_errors) { $filterent = array(); $filterent['id'] = $_POST['ruleid']>0?$_POST['ruleid']:''; @@ -366,6 +388,24 @@ if ($_POST) { if (isset($_POST['interface'] )) $filterent['interface'] = $_POST['interface']; + if ($_POST['tcpflags_any']) { + $filterent['tcpflags_any'] = true; + } else { + $settcpflags = array(); + $outoftcpflags = array(); + foreach ($tcpflags as $tcpflag) { + if ($_POST['tcpflags1_' . $tcpflag] == "on") + $settcpflags[] = $tcpflag; + if ($_POST['tcpflags2_' . $tcpflag] == "on") + $outoftcpflags[] = $tcpflag; + } + if (!empty($outoftcpflags)) { + $filterent['tcpflags2'] = join(",", $outoftcpflags); + if (!empty($settcpflags)) + $filterent['tcpflags1'] = join(",", $settcpflags); + } + } + if ($if == "FloatingRules" || isset($_POST['floating'])) { if (isset($_POST['tag'])) $filterent['tag'] = $_POST['tag']; @@ -1004,6 +1044,48 @@ include("head.inc"); </div> </td> </tr> + <tr id="tcpflags" name="tcpflags"> + <td width="22%" valign="top" class="vncell">TCP flags</td> + <td width="78%" class="vtable"> + <div id="showtcpflagsbox"> + <input type="button" onClick="show_advanced_tcpflags()" value="Advanced"></input> - Show advanced option</a> + </div> + <div id="showtcpflagsadv" style="display:none"> + <div id="tcpheader" name="tcpheader"> + <center> + <table border="0" cellspacing="0" cellpadding="0"> + <?php + $setflags = explode(",", $pconfig['tcpflags1']); + $outofflags = explode(",", $pconfig['tcpflags2']); + $header = "<td width='40' nowrap></td>"; + $tcpflags1 = "<td width='40' nowrap>set</td>"; + $tcpflags2 = "<td width='40' nowrap>out of</td>"; + foreach ($tcpflags as $tcpflag) { + $header .= "<td width='40' nowrap><strong>" . strtoupper($tcpflag) . "</strong></td>\n"; + $tcpflags1 .= "<td width='40' nowrap> <input type='checkbox' name='tcpflags1_{$tcpflag}' value='on' "; + if (array_search($tcpflag, $setflags) !== false) + $tcpflags1 .= "checked"; + $tcpflags1 .= "></td>\n"; + $tcpflags2 .= "<td width='40' nowrap> <input type='checkbox' name='tcpflags2_{$tcpflag}' value='on' "; + if (array_search($tcpflag, $outofflags) !== false) + $tcpflags2 .= "checked"; + $tcpflags2 .= "></td>\n"; + } + echo "<tr id='tcpheader' name='tcpheader'>{$header}</tr>\n"; + echo "<tr id='tcpflags1' name='tcpflags1'>{$tcpflags1}</tr>\n"; + echo "<tr id='tcpflags2' name='tcpflags2'>{$tcpflags2}</tr>\n"; + ?> + </table> + <center> + </div> + <br/><center> + <input onClick='tcpflags_anyclick(this);' type='checkbox' name='tcpflags_any' value='on' <?php if ($pconfig['tcpflags_any']) echo "checked"; ?>><strong>Any flags.</strong><br/></center> + <br/> + <span class="vexpl">Use this to choose TCP flags that must + be set or cleared for this rule to match.</span> + </div> + </td> + </tr> <tr> <td width="22%" valign="top" class="vncell">State Type</td> <td width="78%" class="vtable"> @@ -1013,12 +1095,14 @@ include("head.inc"); <div id="showstateadv" style="display:none"> <select name="statetype"> <option value="keep state" <?php if(!isset($pconfig['statetype']) or $pconfig['statetype'] == "keep state") echo "selected"; ?>>keep state</option> + <option value="sloppy state" <?php if($pconfig['statetype'] == "sloppy state") echo "selected"; ?>>sloppy state</option> <option value="synproxy state"<?php if($pconfig['statetype'] == "synproxy state") echo "selected"; ?>>synproxy state</option> <option value="none"<?php if($pconfig['statetype'] == "none") echo "selected"; ?>>none</option> </select><br>HINT: Select which type of state tracking mechanism you would like to use. If in doubt, use keep state. <p> <table width="90%"> <tr><td width="25%"><ul><li>keep state</li></td><td>Works with all IP protocols.</ul></td></tr> + <tr><td width="25%"><ul><li>sloppy state</li></td><td>Works with all IP protocols.</ul></td></tr> <tr><td width="25%"><ul><li>synproxy state</li></td><td>Proxies incoming TCP connections to help protect servers from spoofed TCP SYN floods. This option includes the functionality of keep state and modulate state combined.</ul></td></tr> <tr><td width="25%"><ul><li>none</li></td><td>Do not use state mechanisms to keep track. This is only useful if you're doing advanced queueing in certain situations. Please check the documentation.</ul></td></tr> </table> diff --git a/usr/local/www/guiconfig.inc b/usr/local/www/guiconfig.inc index 0de2f2d..af906cb 100755 --- a/usr/local/www/guiconfig.inc +++ b/usr/local/www/guiconfig.inc @@ -93,20 +93,20 @@ if(!$ignorefirmwarelock) { } $firewall_rules_dscp_types = array("af11", - "af12", - "af13", - "af21", - "af22", - "af23", - "af31", - "af32", - "af33", - "af41", - "af42", - "af43", - "EF", - "1-64", - "0x04-0xfc"); + "af12", + "af13", + "af21", + "af22", + "af23", + "af31", + "af32", + "af33", + "af41", + "af42", + "af43", + "EF", + "1-64", + "0x04-0xfc"); $auth_server_types = array( 'ldap' => "LDAP", @@ -202,6 +202,9 @@ $wkports = array( 69 => "TFTP", 5900 => "VNC"); +/* TCP flags */ +$tcpflags = array("fin", "syn", "rst", "psh", "ack", "urg"); + $specialnets = array("wanip" => "WAN address", "lanip" => "LAN address", "lan" => "LAN net", "pptp" => "PPTP clients", "pppoe" => "PPPoE clients", "l2tp" => "L2TP clients"); $spiflist = get_configured_interface_with_descr(true, true); diff --git a/usr/local/www/javascript/firewall_rules_edit/firewall_rules_edit.js b/usr/local/www/javascript/firewall_rules_edit/firewall_rules_edit.js index 1b7f33a..2aefe92 100644 --- a/usr/local/www/javascript/firewall_rules_edit/firewall_rules_edit.js +++ b/usr/local/www/javascript/firewall_rules_edit/firewall_rules_edit.js @@ -90,8 +90,10 @@ function typesel_change() { function proto_change() { if (document.iform.proto.selectedIndex < 3) { portsenabled = 1; + document.getElementById("tcpflags").style.display = ''; } else { portsenabled = 0; + document.getElementById("tcpflags").style.display = 'none'; } /* Disable OS knob if the proto is not TCP. */ @@ -180,6 +182,12 @@ function show_advanced_state() { aodiv.style.display = "block"; } +function show_advanced_tcpflags() { + document.getElementById("showtcpflagsbox").innerHTML=''; + aodiv = document.getElementById('showtcpflagsadv'); + aodiv.style.display = "block"; +} + function show_advanced_layer7() { document.getElementById("showadvlayer7box").innerHTML=''; aodiv = document.getElementById('showlayer7adv'); @@ -194,4 +202,11 @@ function dst_rep_change() { document.iform.dstendport.selectedIndex = document.iform.dstbeginport.selectedIndex; } +function tcpflags_anyclick(obj) { + if (obj.checked) { + document.getElementById('tcpheader').style.display= 'none'; + } else { + document.getElementById('tcpheader').style.display= ""; + } +} //--> |