[ previous ] [ next ] [ threads ]
 
 From:  edward mzj <edward dot mzj at gmail dot com>
 To:  m0n0wall at lists dot m0n0 dot ch
 Subject:  A few modification to m0n0, anyone interested?
 Date:  Sun, 7 Aug 2005 02:45:31 +0800
hi guys, i just added a few codes to m0n0, enabling inbound/outbound
nat on lan interface, policy outbound nat, and inbound load-balancing
on a simple round-robin basis. anyone interested?

inbound/outbound nat on lan-if and policy outbound nat make it
possible to do a few things like: redirecting service to a host on the
same subnet, transparent proxying with squid for example; allowing
client to access redirected services from within lan side without the
need of dns-masquading, etc.

round-robin load-balancing for redirected inbound service, you know
its meaning, right!?

it's almost 3AM CST now and i'm a little bit sleepy. so i will give
detailed setup and usage information in my next email

sorry for my poor english. the following is the patch file. patch -p3
< patch-file to apply.

---------BEGIN OF PATCH FILE----------
diff -burN /mnt/vn3/etc/inc/filter.inc /mnt/vn4/etc/inc/filter.inc
--- /mnt/vn3/etc/inc/filter.inc Sun Jun 19 17:58:27 2005
+++ /mnt/vn4/etc/inc/filter.inc Sun Aug  7 01:45:48 2005
@@ -130,6 +130,17 @@
return $natrule;
}

+function filter_nat_rules_generate_if_ext($if, $src, $dst, $dstport,
$target, $proto) {
+
+ if ($target)
+ $tgt = $target . "/32";
+ else
+ $tgt = "0/32";
+
+ return "map $if $src $dst $dstport -> {$tgt} portmap $proto auto";
+ //return $natrule;
+}
+
function filter_nat_rules_generate() {
global $config, $g;

@@ -182,6 +193,18 @@
else
$natif = $config['interfaces'][$obent['interface']]['if'];

+ if (isset($obent['dst-port-enable'])){
+ list($beginport,$endport) = explode("-",$obent['dst-port']);
+ if (isset($endport)){
+ $beginport--;
+ $endport++;
+ $dstport = "port " . $beginport . " >< " . $endport;
+ }
+ else
+ $dstport = "port = " . $beginport;
+ $natrules .= filter_nat_rules_generate_if_ext($natif, $src, 
+ $dst, $dstport, $obent['target'], $obent['protocol']);
+ } else 
$natrules .= filter_nat_rules_generate_if($natif, $src, $dst,
$obent['target']);
}
@@ -233,9 +256,16 @@
if (!$target)
continue; /* unresolvable alias */

- if ($rule['external-address'])
- $extaddr = $rule['external-address'] . "/32";
+ if ($rule['external-address']){
+ $extaddr = $rule['external-address'];
+ if ( !is_ipaddr($extaddr) ){
+ if ( "wan" == $extaddr )
+ $extaddr = get_current_wan_address();
else
+ $extaddr = $config['interface'][$extaddr]['ipaddr'];
+ }
+ $extaddr .= "/32";
+ } else
$extaddr = "0/0";

if (!$rule['interface'] || ($rule['interface'] == "wan"))
@@ -253,6 +283,9 @@
"-> {$target} " .
"port {$rule['local-port']} {$rule['protocol']}";
}
+ # round-robin load-balancing support
+ if ($rule['roundrobin'])
+ $natrules .= " round-robin";

$natrules .= "\n";
}
diff -burN /mnt/vn3/etc/rc.newwanip /mnt/vn4/etc/rc.newwanip
--- /mnt/vn3/etc/rc.newwanip Sun Jun 19 17:58:27 2005
+++ /mnt/vn4/etc/rc.newwanip Sun Aug  7 01:45:29 2005
@@ -55,7 +55,8 @@
}

/* reload firewall rules */
- filter_rules_generate();
+ //filter_rules_generate();
+ filter_configure();

/* flush NAT table */
filter_flush_nat_table();
diff -burN /mnt/vn3/usr/local/www/firewall_nat.php
/mnt/vn4/usr/local/www/firewall_nat.php
--- /mnt/vn3/usr/local/www/firewall_nat.php Sun Jun 19 17:58:18 2005
+++ /mnt/vn4/usr/local/www/firewall_nat.php Sun Aug  7 01:45:57 2005
@@ -102,6 +102,8 @@
                 <tr valign="top"> 
  <td class="listlr">
                   <?php
+ if ($natent['interface'] == "lan")
+ echo "LAN";
if (!$natent['interface'] || ($natent['interface'] == "wan"))
echo "WAN";
else
@@ -124,8 +126,17 @@
                   </td>
                   <td class="listr"> 
                     <?=$natent['target'];?>
- <?php if ($natent['external-address'])
- echo "<br>(ext.: " . $natent['external-address'] . ")";
+ <?php if ($natent['external-address']){
+ $extaddr = $natent['external-address'];
+ if ( !is_ipaddr($extaddr) ){
+ if ( "wan" == $extaddr || "lan" == $extaddr )
+ echo "<br>(ext.: " . strtoupper($extaddr)  . " Addr)";
+ else
+ echo "<br>(ext.: " . $config['interface'][$extaddr]['descr'] . ")";
+ } else
+ echo "<br>(ext.: " . $extaddr . ")";
+ } else
+ echo "<br>(ext.: Any Addr)";
?>
                   </td>
                   <td class="listr"> 
diff -burN /mnt/vn3/usr/local/www/firewall_nat_edit.php
/mnt/vn4/usr/local/www/firewall_nat_edit.php
--- /mnt/vn3/usr/local/www/firewall_nat_edit.php Sun Jun 19 17:58:18 2005
+++ /mnt/vn4/usr/local/www/firewall_nat_edit.php Sun Aug  7 01:45:57 2005
@@ -50,6 +50,9 @@
$pconfig['localbeginport'] = $a_nat[$id]['local-port'];
$pconfig['descr'] = $a_nat[$id]['descr'];
$pconfig['interface'] = $a_nat[$id]['interface'];
+    $pconfig['roundrobin'] = $a_nat[$id]['roundrobin'];
+    //$pconfig['auto_policy_nat'] = $a_nat[$id]['auto-policy-nat'];
+
if (!$pconfig['interface'])
$pconfig['interface'] = "wan";
} else {
@@ -140,6 +143,8 @@
$natent['local-port'] = $_POST['localbeginport'];
$natent['interface'] = $_POST['interface'];
$natent['descr'] = $_POST['descr'];
+        $natent['roundrobin'] = $_POST['roundrobin'];
+ //$natent['auto-policy-nat']=$_POST['auto_policy_nat'];

if (isset($id) && $a_nat[$id])
$a_nat[$id] = $natent;
@@ -215,7 +220,7 @@
                   <td width="78%" class="vtable">
<select name="interface" class="formfld">
<?php
- $interfaces = array('wan' => 'WAN');
+ $interfaces = array('wan' => 'WAN', 'lan' => 'LAN');
for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) {
$interfaces['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];
}
@@ -232,7 +237,15 @@
                   <td width="22%" valign="top"
class="vncellreq">External address</td>
                   <td width="78%" class="vtable"> 
                     <select name="extaddr" class="formfld">
-   <option value="" <?php if (!$pconfig['extaddr']) echo "selected";
?>>Interface address</option>
+ <?php
+ $interfaces = array('wan' => 'WAN Address', 'lan' => 'LAN Address');
+ for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) {
+ $interfaces['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];
+ }
+ foreach ($interfaces as $iface => $ifaceaddr): ?>
+ <option value="<?=$iface;?>" <?php if ($iface ==
$pconfig['extaddr']) echo "selected"; ?>>
+ <?=htmlspecialchars($ifaceaddr);?></option> <?php endforeach; ?>
+   <option value="" <?php if (!$pconfig['extaddr']) echo "selected";
?>>Any address</option>
                       <?php
  if (is_array($config['nat']['servernat'])):
  foreach ($config['nat']['servernat'] as $sn): ?>
@@ -329,7 +342,29 @@
                     <input name="descr" type="text" class="formfld"
id="descr" size="40"
value="<?=htmlspecialchars($pconfig['descr']);?>">
                     <br> <span class="vexpl">You may enter a description here 
                     for your reference (not parsed).</span></td>
-                </tr><?php if (!(isset($id) && $a_nat[$id])): ?>
+                </tr>
+                <tr>
+                  <td width="22%" valign="top"
class="vncell">Load-balacing</td>
+                  <td width="78%" class="vtable">
+                    <input name="roundrobin" type="checkbox"
id="roundrobin" value="yes" <?php if ($pconfig['roundrobin']) echo
"checked"; ?>>
+                    <strong>Enable round-robin
load-balancing.</strong> <br> <span class="vexpl">Those inbound nat
mappings with the
+                    same external IP and Port pairs will be
load-balanced on a simple round-robin basis.
+ <br><br><strong>Note: </strong>This may cause undesired behavior
because of this simple load-balancing scheme.
+ <br>And m0n0wall has no knowledge whether each server is alive.
+ <br>Use with caution.</span></td>
+                </tr> 
+ <!--
+                <tr> 
+                  <td width="22%" valign="top">&nbsp;</td>
+                  <td width="78%"> 
+                    <input name="auto_policy_nat" type="checkbox"
id="auto_policy_nat" value="yes" <?php if
($pconfig['auto_policy_nat']) echo "checked"; ?>>
+                    <strong>Auto generate policy NAT rules on each
other interfaces to allow users to access the redirected
service<br></strong>
+ <span class="vexpl">Note: these rules will not be generated and must
be added manually if Advanced Outbound NAT is enabled.
+ <br>Caution: This might be helpful if the client app doesn't support
DNS. However it might cause performance issue under
+ heavy network load. Consider DNS-masquading in that situation</span></td>
+                </tr>
+ //-->
+ <?php if (!(isset($id) && $a_nat[$id])): ?>
                 <tr> 
                   <td width="22%" valign="top">&nbsp;</td>
                   <td width="78%"> 
diff -burN /mnt/vn3/usr/local/www/firewall_nat_out.php
/mnt/vn4/usr/local/www/firewall_nat_out.php
--- /mnt/vn3/usr/local/www/firewall_nat_out.php Sun Jun 19 17:58:18 2005
+++ /mnt/vn4/usr/local/www/firewall_nat_out.php Sun Aug  7 01:45:57 2005
@@ -114,17 +114,20 @@
               </table>
               <table width="100%" border="0" cellpadding="0" cellspacing="0">
                 <tr> 
-                  <td width="10%" class="listhdrr">Interface</td>
-                  <td width="20%" class="listhdrr">Source</td>
-                  <td width="20%" class="listhdrr">Destination</td>
-                  <td width="20%" class="listhdrr">Target</td>
-                  <td width="25%" class="listhdr">Description</td>
+                  <td width="5%" class="listhdrr">If</td>
+                  <td width="15%" class="listhdrr">Source</td>
+                  <td width="15%" class="listhdrr">Destination</td>
+                  <td width="25%" class="listhdrr">Policy NAT</td>
+                  <td width="15%" class="listhdrr">Target</td>
+                  <td width="20%" class="listhdr">Description</td>
                   <td width="5%" class="list"></td>
                 </tr>
               <?php $i = 0; foreach ($a_out as $natent): ?>
                 <tr> 
                   <td class="listlr">
                     <?php
+ if ($natent['interface'] == "lan")
+ echo "LAN";
if (!$natent['interface'] || ($natent['interface'] == "wan"))
   echo "WAN";
else
@@ -147,6 +150,20 @@
                   </td>
                   <td class="listr"> 
                     <?php
+ if (isset($natent['policy-nat-enable'])){
+ list($beginport, $endport) = split("-", $natent['dst-port']);
+ if ((!$endport) || ($beginport == $endport)) {
+ echo strtolower($natent['protocol']) . " : " . $beginport;
+ if ($wkports[$beginport])
+ echo " (" . $wkports[$beginport] . ")";
+ } else
+ echo strtolower($natent['protocol']) . " : " . $beginport . " - " . $endport;
+ } else
+ echo "Disabled";
+   ?>
+                  </td>
+                  <td class="listr"> 
+                    <?php
                       if (!$natent['target'])
                           echo "*";
                       else
@@ -161,7 +178,7 @@
                 </tr>
               <?php $i++; endforeach; ?>
                 <tr> 
-                  <td class="list" colspan="5"></td>
+                  <td class="list" colspan="6"></td>
                   <td class="list"> <a
href="firewall_nat_out_edit.php"><img src="plus.gif" title="add
mapping" width="17" height="17" border="0"></a></td>
                 </tr>
               </table>
diff -burN /mnt/vn3/usr/local/www/firewall_nat_out_edit.php
/mnt/vn4/usr/local/www/firewall_nat_out_edit.php
--- /mnt/vn3/usr/local/www/firewall_nat_out_edit.php Sun Jun 19 17:58:18 2005
+++ /mnt/vn4/usr/local/www/firewall_nat_out_edit.php Sun Aug  7 01:45:57 2005
@@ -62,8 +62,16 @@
     list($pconfig['source'],$pconfig['source_subnet']) = explode('/',
$a_out[$id]['source']['network']);
     network_to_pconfig($a_out[$id]['destination'], $pconfig['destination'],
   $pconfig['destination_subnet'], $pconfig['destination_not']);
+
+    if (isset($a_out[$id]['policy-nat-enable'])){
+ $pconfig['policy_nat_enable']=1;
+ list($pconfig['beginport'],$pconfig['endport']) = explode("-",
$a_out[$id]['dst-port']);
+ } else
+ $pconfig['policy_nat_enable']=0;
+ 
     $pconfig['target'] = $a_out[$id]['target'];
     $pconfig['interface'] = $a_out[$id]['interface'];
+ $pconfig['proto'] = $a_out[$id]['protocol'];
if (!$pconfig['interface'])
$pconfig['interface'] = "wan";
     $pconfig['descr'] = $a_out[$id]['descr'];
@@ -108,6 +116,35 @@
         $input_errors[] = "A valid target IP address must be specified.";
     }
     
+ if  (isset($_POST[policy_nat_enable])){
+ if ($_POST['beginport_cust'] && !$_POST['beginport'])
+ $_POST['beginport'] = $_POST['beginport_cust'];
+ if ($_POST['endport_cust'] && !$_POST['endport'])
+ $_POST['endport'] = $_POST['endport_cust'];
+
+ if (!$_POST['endport'])
+ $_POST['endport'] = $_POST['beginport'];
+ 
+ if ($_POST['beginport'] ===""){
+ $input_errors[] = "The start port must be an integer between 1 and 65535.";
+ }
+ if (($_POST['beginport'] && !is_port($_POST['beginport']))) {
+ $input_errors[] = "The start port must be an integer between 1 and 65535.";
+ }
+ if (($_POST['endport'] && !is_port($_POST['endport']))) {
+ $input_errors[] = "The end port must be an integer between 1 and 65535.";
+ }
+ if ($_POST['beginport'] > $_POST['endport']) {
+ /* swap */
+ $tmp = $_POST['endport'];
+ $_POST['endport'] = $_POST['beginport'];
+ $_POST['beginport'] = $tmp;
+ }
+ if (!$input_errors && $_POST[endport] > 65535) {
+ $input_errors[] = "The target port range must lie between 1 and 65535.";
+ }
+ }
+    
     /* check for existing entries */
     $osn = gen_subnet($_POST['source'], $_POST['source_subnet']) .
"/" . $_POST['source_subnet'];
     if ($_POST['destination_type'] == "any")
@@ -152,6 +189,7 @@
         $natent['descr'] = $_POST['descr'];
         $natent['target'] = $_POST['target'];
         $natent['interface'] = $_POST['interface'];
+        $natent['protocol'] = $_POST['proto'];
         
         if ($ext == "any")
             $natent['destination']['any'] = true;
@@ -161,6 +199,17 @@
         if (isset($_POST['destination_not']) && $ext != "any")
             $natent['destination']['not'] = true;
         
+ if (isset($_POST[policy_nat_enable])){
+ $natent['policy-nat-enable'] = true; 
+ if ($_POST['beginport'] == $_POST['endport'])
+ $natent['dst-port'] = $_POST['beginport'];
+ else
+ $natent['dst-port'] = $_POST['beginport'] . "-" . $_POST['endport'];
+ } else {
+ $natent['policy-nat-enable'] = false;
+ $natent['dst-port'] = "";
+ }
+ 
         if (isset($id) && $a_out[$id])
             $a_out[$id] = $natent;
         else
@@ -178,6 +227,41 @@
<?php include("fbegin.inc"); ?>
<script language="JavaScript">
<!--
+function ext_change() {
+ if (document.iform.beginport.selectedIndex == 0) {
+ document.iform.beginport_cust.disabled = 0;
+ } else {
+ document.iform.beginport_cust.value = "";
+ document.iform.beginport_cust.disabled = 1;
+ }
+ if (document.iform.endport.selectedIndex == 0) {
+ document.iform.endport_cust.disabled = 0;
+ } else {
+ document.iform.endport_cust.value = "";
+ document.iform.endport_cust.disabled = 1;
+ }
+ /*
+ if (document.iform.localbeginport.selectedIndex == 0) {
+ document.iform.localbeginport_cust.disabled = 0;
+ } else {
+ document.iform.localbeginport_cust.value = "";
+ document.iform.localbeginport_cust.disabled = 1;
+ }
+ */
+}
+function ext_rep_change() {
+ document.iform.endport.selectedIndex = document.iform.beginport.selectedIndex;
+ //document.iform.localbeginport.selectedIndex =
document.iform.beginport.selectedIndex;
+}
+
+function policy_nat_enable_Change() {
+ document.iform.proto.disabled = !document.iform.policy_nat_enable.checked;
+ document.iform.beginport.disabled = !document.iform.policy_nat_enable.checked;
+ document.iform.endport.disabled = !document.iform.policy_nat_enable.checked;
+ document.iform.beginport_cust.disabled =
!document.iform.policy_nat_enable.checked;
+ document.iform.endport_cust.disabled =
!document.iform.policy_nat_enable.checked;
+}
+
function typesel_change() {
     switch (document.iform.destination_type.selectedIndex) {
         case 1: // network
@@ -202,7 +286,7 @@
                   <td width="78%" class="vtable">
<select name="interface" class="formfld">
<?php
- $interfaces = array('wan' => 'WAN');
+ $interfaces = array('wan' => 'WAN', 'lan' => 'LAN');
for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) {
$interfaces['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];
}
@@ -219,8 +303,6 @@
                   <td width="22%" valign="top" class="vncellreq">Source</td>
                   <td width="78%" class="vtable">
<?=$mandfldhtml;?><input name="source" type="text" class="formfld"
id="source" size="20"
value="<?=htmlspecialchars($pconfig['source']);?>">
-                     
-                  / 
                     <select name="source_subnet" class="formfld"
id="source_subnet">
                       <?php for ($i = 32; $i >= 0; $i--): ?>
                       <option value="<?=$i;?>" <?php if ($i ==
$pconfig['source_subnet']) echo "selected"; ?>>
@@ -253,7 +335,6 @@
                         <td>Address:&nbsp;&nbsp;</td>
<td><?=$mandfldhtmlspc;?></td>
                         <td><input name="destination" type="text"
class="formfld" id="destination" size="20"
value="<?=htmlspecialchars($pconfig['destination']);?>">
-                          / 
                           <select name="destination_subnet"
class="formfld" id="destination_subnet">
                             <?php for ($i = 32; $i >= 0; $i--): ?>
                             <option value="<?=$i;?>" <?php if ($i ==
$pconfig['destination_subnet']) echo "selected"; ?>>
@@ -271,9 +352,67 @@
                     </table></td>
                 </tr>
                 <tr> 
+                  <td width="22%" valign="top" class="vncell">Policy NAT </td>
+                  <td width="78%" class="vtable"> 
+ <input name="policy_nat_enable" type="checkbox"
id="policy_nat_enable" onChange=policy_nat_enable_Change() value="yes"
<?php if ($pconfig['policy_nat_enable']) echo "checked"; ?>>
+                    <strong>Enable</strong><br>
+                    Use this option to enable policy nat<br>
+                    <br>
+                    <table border="0" cellspacing="0" cellpadding="0">
+ <tr> 
+   <td>Protocol:&nbsp;&nbsp;</td>
+   <td> <select name="proto" class="formfld" <?php if
(!$pconfig['policy_nat_enable']) echo "disabled"; ?>>
+   <?php $protocols = explode(" ", "TCP UDP TCP/UDP"); foreach
($protocols as $proto): ?>
+   <option value="<?=strtolower($proto);?>" <?php if
(strtolower($proto) == $pconfig['proto']) echo "selected";
?>><?=htmlspecialchars($proto);?></option>
+   <?php endforeach; ?>
+ </select> </td>
+ </tr>
+                        <td>&nbsp;</td>
+     <td><span class="vexpl">Choose which IP protocol this rule
should match.<br>
+ Hint: in most cases, you should specify <em>TCP</em> &nbsp;here.<br>
&nbsp;</span></td>
+ </tr>
+ <tr> 
+                        <td>from:&nbsp;&nbsp;</td>
+                        <td><select name="beginport" class="formfld"
onChange="ext_rep_change();ext_change()" <?php if
(!$pconfig['policy_nat_enable']) echo "disabled"; ?>>
+                            <option value="">(other)</option>
+                            <?php $bfound = 0; foreach ($wkports as
$wkport => $wkportdesc): ?>
+                            <option value="<?=$wkport;?>" <?php if
($wkport == $pconfig['beginport']) {
+ echo "selected";
+ $bfound = 1;
+ }?>>
+ <?=htmlspecialchars($wkportdesc);?>
+ </option>
+                            <?php endforeach; ?>
+                          </select> <input name="beginport_cust"
type="text" size="5" value="<?php if (!$bfound) echo
$pconfig['beginport']; ?>" <?php if (!$pconfig['policy_nat_enable'])
echo "disabled"; ?>></td>
+                      </tr>
+                      <tr> 
+                        <td>to:&nbsp;&nbsp;</td>
+                        <td><select name="endport" class="formfld"
onChange="ext_change()" <?php if (!$pconfig['policy_nat_enable']) echo
"disabled"; ?>>
+                            <option value="">(other)</option>
+                            <?php $bfound = 0; foreach ($wkports as
$wkport => $wkportdesc): ?>
+                            <option value="<?=$wkport;?>" <?php if
($wkport == $pconfig['endport']) {
+ echo "selected";
+ $bfound = 1;
+ }?>>
+ <?=htmlspecialchars($wkportdesc);?>
+ </option>
+ <?php endforeach; ?>
+                            </select> <input name="endport_cust"
type="text" size="5" value="<?php if (!$bfound) echo
$pconfig['endport']; ?>" <?php if (!$pconfig['policy_nat_enable'])
echo "disabled"; ?>>
+ </td>
+                      </tr>
+ <tr>
+                        <td>&nbsp;</td>
+     <td><span class="vexpl">Specify the port or port range on 
+ destination address for this mapping.<br>
+ Hint: you can leave the <em>'to'</em> field empty if you only 
+ want to map a single port</span></td>
+ </tr>
+                    </table></td>
+                </tr>
+                <tr> 
                   <td valign="top" class="vncell">Target</td>
                   <td class="vtable">
-<input name="target" type="text" class="formfld" id="target"
size="20" value="<?=htmlspecialchars($pconfig['target']);?>">
+ <input name="target" type="text" class="formfld" id="target"
size="20" value="<?=htmlspecialchars($pconfig['target']);?>">
                     <br>
                      <span class="vexpl">Packets matching this rule
will be mapped to the IP address given here. Leave blank to use the
selected interface's IP address.</span></td>
                 </tr>
---------END OF PATCH FILE----------