[ previous ] [ next ] [ threads ]
 
 From:  Petr Verner <verner at ipps dot cz>
 To:  m0n0wall at lists dot m0n0 dot ch
 Subject:  another new suggestion
 Date:  Tue, 14 Oct 2003 16:04:38 +0200
hello,

   m0n0wall is great work. but I have one suggestion: could be advanced 
outbound NAT more advanced :-) ? I mean, with ipnat you can do not only:
map fxp0 10.1.0.0/16 -> 0.0.0.0/32
but also:
map fxp0 from 10.1.0.0/16 to 192.168.0.0/16 -> 0.0.0.0/32
or even:
map fxp0 from 10.1.0.0/16 ! to 192.168.0.0/16 -> 0.0.0.0/32

it means: do NAT on packets which goes only to 192.168.0.0/16 network
(resp. do NAT on all packets except those that goes to 192.168.0.0/16 network)

I've already made this changes, so I hope you find it usable:

/etc/inc/filter.inc.diff
=========================================
--- rootfs-pb18r522/etc/inc/filter.inc	2003-10-11 22:46:37.000000000 +0200
+++ patch/etc/inc/filter.inc	2003-10-09 14:42:55.000000000 +0200
@@ -93,11 +93,11 @@
 	return mwexec("/sbin/ipf -FS");
 }
 
-function filter_nat_rules_generate_if($if, $sa, $sn, $mssclamp) {
+function filter_nat_rules_generate_if($if, $src, $dst, $mssclamp) {
 	$natrule = <<<EOD
-map $if $sa/$sn -> 0/32 proxy port ftp ftp/tcp $mssclamp
-map $if $sa/$sn -> 0/32 portmap tcp/udp auto $mssclamp
-map $if $sa/$sn -> 0/32 $mssclamp
+map $if $src $dst -> 0/32 proxy port ftp ftp/tcp $mssclamp
+map $if $src $dst -> 0/32 portmap tcp/udp auto $mssclamp
+map $if $src $dst -> 0/32 $mssclamp
 
 EOD;
 
@@ -136,13 +136,23 @@
 		/* advanced outbound rules */
 		if (is_array($config['nat']['advancedoutbound']['rule'])) {
 			foreach ($config['nat']['advancedoutbound']['rule'] as $obent) {
-				list($sa,$sn) = explode("/", $obent['source']);
-				$natrules .= filter_nat_rules_generate_if($wanif, $sa, $sn, $mssclamp);
+				$dst = "";
+				$src = "";
+				if (!isset($obent['destination']['any'])) {
+					$src = "from ";
+					if (isset($obent['destination']['not'])) 
+						$dst = "! to ";
+					else
+						$dst = "to ";
+					$dst .= $obent['destination']['network'];
+				}
+				$src .= $obent['source']['network'];
+				$natrules .= filter_nat_rules_generate_if($wanif, $src, $dst, $mssclamp);
 			}
 		}	
 	} else {
 		/* standard outbound rules (one for each interface) */
-		$natrules .= filter_nat_rules_generate_if($wanif, $lansa, 
$lancfg['subnet'], $mssclamp);
+		$natrules .= filter_nat_rules_generate_if($wanif, 
$lansa."/".$lancfg['subnet'], "", $mssclamp);
 	
 		/* optional interfaces */
 		for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) {
@@ -150,7 +160,7 @@
 			
 			if (isset($optcfg['enable'])) {
 				$optsa = gen_subnet($optcfg['ipaddr'], $optcfg['subnet']);
-				$natrules .= filter_nat_rules_generate_if($wanif, $optsa, 
$optcfg['subnet'], $mssclamp);
+				$natrules .= filter_nat_rules_generate_if($wanif, 
$optsa."/".$optcfg['subnet'], "", $mssclamp);
 			}
 		}
 	}
=======================================================
/usr/local/www/firewall_nat_out.php.diff
=======================================================
--- rootfs-pb18r522/usr/local/www/firewall_nat_out.php	2003-10-11 
22:46:37.000000000 +0200
+++ patch/usr/local/www/firewall_nat_out.php	2003-10-09 14:53:46.000000000 
+0200
@@ -98,7 +98,7 @@
     <td width="100%">&nbsp;</td>
   </tr>
   <tr> 
-    <td colspan="4" class="tabcont">
+    <td colspan="6" class="tabcont">
               <table width="100%" border="0" cellpadding="6" cellspacing="0">
                 <tr> 
                   <td class="vtable"><p>
@@ -125,14 +125,25 @@
               &nbsp;<br>
               <table width="100%" border="0" cellpadding="0" cellspacing="0">
                 <tr> 
-                  <td width="30%" class="listhdrr">Internal subnet</td>
-                  <td width="60%" class="listhdr">Description</td>
+                  <td width="20%" class="listhdrr">Internal subnet</td>
+                  <td width="20%" class="listhdrr">External subnet</td>
+                  <td width="50%" class="listhdr">Description</td>
                   <td width="10%" class="list"></td>
 				</tr>
 			  <?php $i = 0; foreach ($a_out as $natent): ?>
                 <tr> 
                   <td class="listlr"> 
-                    <?=$natent['source'];?>
+                    <?=$natent['source']['network'];?>
+                  </td>
+                  <td class="listr"> 
+		    <?php if (isset($natent['destination']['any']))
+				echo "*";
+			  else {
+				if (isset($natent['destination']['not']))
+					echo "!&nbsp;";
+                                echo $natent['destination']['network'];
+			  } ?>
+			  
                   </td>
                   <td class="listbg"> 
                     <?=htmlspecialchars($natent['descr']);?>&nbsp;
@@ -142,7 +153,7 @@
 				</tr>
 			  <?php $i++; endforeach; ?>
                 <tr> 
-                  <td class="list" colspan="2"></td>
+                  <td class="list" colspan="3"></td>
                   <td class="list"> <a href="firewall_nat_out_edit.php"><img 
src="plus.gif" width="17" height="17" border="0"></a></td>
 				</tr>
               </table>
=========================================================
firewall_nat_out_edit.php.diff
=========================================================
--- rootfs-pb18r522/usr/local/www/firewall_nat_out_edit.php	2003-10-11 
22:46:37.000000000 +0200
+++ patch/usr/local/www/firewall_nat_out_edit.php	2003-10-08 
12:42:22.000000000 +0200
@@ -41,21 +41,46 @@
 if (isset($_POST['id']))
 	$id = $_POST['id'];
 
+function network_to_pconfig($adr, &$padr, &$pmask, &$pnot) {
+
+        if (isset($adr['any']))
+                $padr = "any";
+        else if ($adr['network']) {
+                list($padr, $pmask) = explode("/", $adr['network']);
+                if (!$pmask)
+                        $pmask = 32;
+        }
+
+        if (isset($adr['not']))
+                $pnot = 1;
+        else
+                $pnot = 0;
+}
+
 if (isset($id) && $a_out[$id]) {
-	list($pconfig['source'],$pconfig['source_subnet']) = explode('/', 
$a_out[$id]['source']);
+	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']);
 	$pconfig['descr'] = $a_out[$id]['descr'];
 } else {
 	$pconfig['source_subnet'] = 24;
+	$pconfig['destination'] = "any";
+	$pconfig['destination_subnet'] = 24;
 }
 
 if ($_POST) {
+
+	if ($_POST['destination_type'] == "any") {
+                $_POST['destination'] = $_POST['destination_type'];
+                $_POST['destination_subnet'] = 24;
+        }
 	
 	unset($input_errors);
 	$pconfig = $_POST;
 
 	/* input validation */
-	$reqdfields = explode(" ", "source source_subnet");
-	$reqdfieldsn = explode(",", "Internal subnet,Internal subnet bit count");
+	$reqdfields = explode(" ", "source source_subnet destination 
destination_subnet");
+	$reqdfieldsn = explode(",", "Internal subnet,Internal subnet bit 
count,External subnet,External subnet bit count");
 	
 	do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
 
@@ -65,22 +90,52 @@
 	if (($_POST['source_subnet'] && !is_numeric($_POST['source_subnet']))) {
 		$input_errors[] = "A valid internal subnet bit count must be specified.";
 	}
+
+	if ($_POST['destination_type'] != "any") {
+                if (($_POST['destination'] && 
!is_ipaddr($_POST['destination']))) {
+                        $input_errors[] = "A valid external subnet must be 
specified.";
+                }
+                if (($_POST['destination_subnet'] && 
!is_numeric($_POST['destination_subnet']))) {
+                        $input_errors[] = "A valid external subnet bit count 
must be specified.";
+                }
+        }
+
 	
 	/* check for existing entries */
 	$osn = gen_subnet($_POST['source'], $_POST['source_subnet']) . "/" . 
$_POST['source_subnet'];
+	if ($_POST['destination_type'] == "any")
+		$ext = "any";
+	else
+		$ext = gen_subnet($_POST['destination'], $_POST['destination_subnet']) . 
"/" . $_POST['destination_subnet'];
+
 	foreach ($a_out as $natent) {
-		if (isset($id) && ($a_out[$id]) && ($a_out[$id] === $natent))
+		if (isset($id) && ($a_out[$id]) && ($a_out[$id] == $natent))
 			continue;
 		
-		if ($natent['source'] == $osn) {
-			$input_errors[] = "There is already an outbound NAT rule for the specified 
internal network.";
-			break;
-		}
+		if ($natent['source']['network'] == $osn)
+			if (isset($natent['destination']['not']) == 
isset($_POST['destination_not']))
+				if ((isset($natent['destination']['any']) && $ext = "any") ||
+				    ($natent['destination']['network'] == $ext)) {
+					$input_errors[] = "There is already an outbound NAT rule for the 
specified internal network.";
+					break;
+				}
 	}
 
 	if (!$input_errors) {
 		$natent = array();
-		$natent['source'] = $osn;
+		$natent['source']['network'] = $osn;
+
+		unset($natent['destination']['not']);
+
+		if ($ext == "any") {
+			unset($natent['destination']['network']);
+			$natent['destination']['any'] = true;
+		} else
+			$natent['destination']['network'] = $ext;
+
+		if (isset($_POST['destination_not']) && $ext != "any")
+			$natent['destination']['not'] = true;
+
 		$natent['descr'] = $_POST['descr'];
 		
 		if (isset($id) && $a_out[$id])
@@ -103,6 +158,24 @@
 <title>m0n0wall webGUI - Firewall: NAT: Edit outbound mapping</title>
 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 <link href="gui.css" rel="stylesheet" type="text/css">
+<script language="JavaScript">
+<!--
+function typesel_change() {
+        switch (document.iform.destination_type.selectedIndex) {
+                case 1: /* network */
+                        document.iform.destination.disabled = 0;
+                        document.iform.destination_subnet.disabled = 0;
+                        break;
+                default:
+                        document.iform.destination.value = "";
+                        document.iform.destination.disabled = 1;
+                        document.iform.destination_subnet.value = 24;
+                        document.iform.destination_subnet.disabled = 1;
+                        break;
+        }
+}
+//-->
+</script>
 </head>
 
 <body link="#0000CC" vlink="#0000CC" alink="#0000CC">
@@ -126,10 +199,40 @@
                     <br> <span class="vexpl">Enter the internal subnet for 
the outbound NAT mapping.</span></td>
                 </tr>
                 <tr> 
+                  <td width="100" valign="top" class="vncellreq">External 
subnet</td>
+                  <td class="vtable"><input name="destination_not" 
type="checkbox" id="destination_not" value="yes" <?php if 
($pconfig['destination_not']) echo "checked"; ?>>
+                    <strong>not</strong><br>
+                    Use this option to invert the sense of the match.<br>
+                    <br>
+                    <table border="0" cellspacing="0" cellpadding="0">
+                      <tr>
+                        <td>Type:&nbsp;&nbsp;</td>
+                        <td><select name="destination_type" class="formfld" 
onChange="typesel_change()">
+                            <option value="any" <?php if 
($pconfig['destination'] == "any") echo "selected"; ?>>
+                            any</option>
+                            <option value="network" <?php if 
($pconfig['destination'] != "any") echo "selected"; ?>>
+                            Network</option>
+                          </select></td>
+                      </tr>
+                      <tr>
+                        <td>Address:&nbsp;&nbsp;</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"; ?>>
+			      <?=$i;?>
+			      </option>
+			      <?php endfor; ?>
+			    </select>
+			    <br> <span class="vexpl">Enter the external subnet for the outbound 
NAT mapping.</span></td>
+                      </tr>
+                    </table></td>
+                </tr>
+                <tr> 
                   <td valign="top" class="vncellreq">Description</td>
                   <td class="vtable"> <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>
+                    <br> <span class="vexpl">You may enter a description here 
for your reference (not parsed).</span></td>
                 </tr>
                 <tr> 
                   <td valign="top">&nbsp;</td>
@@ -141,6 +244,11 @@
                 </tr>
               </table>
 </form>
+<script language="JavaScript">
+<!--
+typesel_change();
+//-->
+</script>
 <?php include("fend.inc"); ?>
 </body>
 </html>
========================================================