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"> </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"> </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: </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: </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> </td>
+ <td><span class="vexpl">Choose which IP protocol this rule
should match.<br>
+ Hint: in most cases, you should specify <em>TCP</em> here.<br>
</span></td>
+ </tr>
+ <tr>
+ <td>from: </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: </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> </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---------- |