Project

General

Profile

Download (19.6 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/* $Id$ */
3
/*
4
	firewall_nat_edit.php
5
	part of m0n0wall (http://m0n0.ch/wall)
6

    
7
	Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
8
	All rights reserved.
9

    
10
	Redistribution and use in source and binary forms, with or without
11
	modification, are permitted provided that the following conditions are met:
12

    
13
	1. Redistributions of source code must retain the above copyright notice,
14
	   this list of conditions and the following disclaimer.
15

    
16
	2. Redistributions in binary form must reproduce the above copyright
17
	   notice, this list of conditions and the following disclaimer in the
18
	   documentation and/or other materials provided with the distribution.
19

    
20
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
21
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
22
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
24
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
	POSSIBILITY OF SUCH DAMAGE.
30
*/
31

    
32
require("guiconfig.inc");
33

    
34
if (!is_array($config['nat']['rule'])) {
35
	$config['nat']['rule'] = array();
36
}
37
//nat_rules_sort();
38
$a_nat = &$config['nat']['rule'];
39

    
40
$id = $_GET['id'];
41
if (isset($_POST['id']))
42
	$id = $_POST['id'];
43

    
44
if (isset($_GET['dup'])) {
45
        $id = $_GET['dup'];
46
        $after = $_GET['dup'];
47
}
48

    
49
if (isset($id) && $a_nat[$id]) {
50
	$pconfig['extaddr'] = $a_nat[$id]['external-address'];
51
	$pconfig['proto'] = $a_nat[$id]['protocol'];
52
	list($pconfig['beginport'],$pconfig['endport']) = explode("-", $a_nat[$id]['external-port']);
53
	$pconfig['localip'] = $a_nat[$id]['target'];
54
	$pconfig['localbeginport'] = $a_nat[$id]['local-port'];
55
	$pconfig['descr'] = $a_nat[$id]['descr'];
56
	$pconfig['interface'] = $a_nat[$id]['interface'];
57
	$pconfig['nosync'] = isset($a_nat[$id]['nosync']);
58
	if (!$pconfig['interface'])
59
		$pconfig['interface'] = "wan";
60
} else {
61
	$pconfig['interface'] = "wan";
62
}
63

    
64
if($id > -1) {
65
	$if = $a_nat[$id]['interface'];
66
	$security_url = "firewall_nat_edit.php?if=". strtolower($if);
67
	if (!isSystemAdmin($HTTP_SERVER_VARS['AUTH_USER'])) {
68
		if(!in_array($security_url, $allowed)) {
69
			// User does not have access
70
	//		echo "displaying error {$security_url}"; print_r($allowed);
71
			echo display_error_form("401", "Unauthorized. You do not have access to edit nat rules on the interface {$if}");
72
			exit;
73
		}
74
	}
75
}
76

    
77
if (isset($_GET['dup']))
78
	unset($id);
79

    
80
/*  run through $_POST items encoding HTML entties so that the user
81
 *  cannot think he is slick and perform a XSS attack on the unwilling 
82
 */
83
foreach ($_POST as $key => $value) {
84
	$temp = $value;
85
	$newpost = htmlentities($temp);
86
	if($newpost <> $temp) 
87
		$input_errors[] = "Invalid characters detected ($temp).  Please remove invalid characters and save again.";		
88
}
89

    
90
if ($_POST) {
91

    
92
	if ($_POST['beginport_cust'] && !$_POST['beginport'])
93
		$_POST['beginport'] = $_POST['beginport_cust'];
94
	if ($_POST['endport_cust'] && !$_POST['endport'])
95
		$_POST['endport'] = $_POST['endport_cust'];
96
	if ($_POST['localbeginport_cust'] && !$_POST['localbeginport'])
97
		$_POST['localbeginport'] = $_POST['localbeginport_cust'];
98

    
99
	if (!$_POST['endport'])
100
		$_POST['endport'] = $_POST['beginport'];
101
        /* Make beginning port end port if not defined and endport is */
102
        if (!$_POST['beginport'] && $_POST['endport'])
103
                $_POST['beginport'] = $_POST['endport'];
104

    
105
	unset($input_errors);
106
	$pconfig = $_POST;
107

    
108
	/* input validation */
109
	if(strtoupper($_POST['proto']) == "TCP" or strtoupper($_POST['proto']) == "UDP" or strtoupper($_POST['proto']) == "TCP/UDP") {
110
		$reqdfields = explode(" ", "interface proto beginport endport localip localbeginport");
111
		$reqdfieldsn = explode(",", "Interface,Protocol,External port from,External port to,NAT IP,Local port");
112
	} else {
113
		$reqdfields = explode(" ", "interface proto localip");
114
		$reqdfieldsn = explode(",", "Interface,Protocol,NAT IP");
115
	}
116

    
117
	do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
118

    
119
	if (($_POST['localip'] && !is_ipaddroralias($_POST['localip']))) {
120
		$input_errors[] = "\"{$_POST['localip']}\" is not valid NAT IP address or host alias.";
121
	}
122

    
123
	/* only validate the ports if the protocol is TCP, UDP or TCP/UDP */
124
	if(strtoupper($_POST['proto']) == "TCP" or strtoupper($_POST['proto']) == "UDP" or strtoupper($_POST['proto']) == "TCP/UDP") {
125

    
126
		if (($_POST['beginport'] && !is_ipaddroralias($_POST['beginport']) && !is_port($_POST['beginport']))) {
127
			$input_errors[] = "The start port must be an integer between 1 and 65535.";
128
		}
129

    
130
		if (($_POST['endport'] && !is_ipaddroralias($_POST['endport']) && !is_port($_POST['endport']))) {
131
			$input_errors[] = "The end port must be an integer between 1 and 65535.";
132
		}
133

    
134
		if (($_POST['localbeginport'] && !is_ipaddroralias($_POST['localbeginport']) && !is_port($_POST['localbeginport']))) {
135
			$input_errors[] = "The local port must be an integer between 1 and 65535.";
136
		}
137

    
138
		if ($_POST['beginport'] > $_POST['endport']) {
139
			/* swap */
140
			$tmp = $_POST['endport'];
141
			$_POST['endport'] = $_POST['beginport'];
142
			$_POST['beginport'] = $tmp;
143
		}
144

    
145
		if (!$input_errors) {
146
			if (($_POST['endport'] - $_POST['beginport'] + $_POST['localbeginport']) > 65535)
147
				$input_errors[] = "The target port range must be an integer between 1 and 65535.";
148
		}
149

    
150
	}
151

    
152
	/* check for overlaps */
153
	foreach ($a_nat as $natent) {
154
		if (isset($id) && ($a_nat[$id]) && ($a_nat[$id] === $natent))
155
			continue;
156
		if ($natent['interface'] != $_POST['interface'])
157
			continue;
158
		if ($natent['external-address'] != $_POST['extaddr'])
159
			continue;
160
		if (($natent['proto'] != $_POST['proto']) && ($natent['proto'] != "tcp/udp") && ($_POST['proto'] != "tcp/udp"))
161
			continue;
162

    
163
		list($begp,$endp) = explode("-", $natent['external-port']);
164
		if (!$endp)
165
			$endp = $begp;
166

    
167
		if (!(   (($_POST['beginport'] < $begp) && ($_POST['endport'] < $begp))
168
		      || (($_POST['beginport'] > $endp) && ($_POST['endport'] > $endp)))) {
169

    
170
			$input_errors[] = "The external port range overlaps with an existing entry.";
171
			break;
172
		}
173
	}
174

    
175
	if (!$input_errors) {
176
		$natent = array();
177
		if ($_POST['extaddr'])
178
			$natent['external-address'] = $_POST['extaddr'];
179
		$natent['protocol'] = $_POST['proto'];
180

    
181
		if ($_POST['beginport'] == $_POST['endport'])
182
			$natent['external-port'] = $_POST['beginport'];
183
		else
184
			$natent['external-port'] = $_POST['beginport'] . "-" . $_POST['endport'];
185

    
186
		$natent['target'] = $_POST['localip'];
187
		$natent['local-port'] = $_POST['localbeginport'];
188
		$natent['interface'] = $_POST['interface'];
189
		$natent['descr'] = $_POST['descr'];
190

    
191
		if($_POST['nosync'] == "yes")
192
			$natent['nosync'] = true;
193
		else
194
			unset($natent['nosync']);
195

    
196
		if (isset($id) && $a_nat[$id])
197
			$a_nat[$id] = $natent;
198
		else {
199
			if (is_numeric($after))
200
				array_splice($a_nat, $after+1, 0, array($natent));
201
			else
202
				$a_nat[] = $natent;
203
		}
204

    
205
		touch($d_natconfdirty_path);
206

    
207
		if ($_POST['autoadd']) {
208
			/* auto-generate a matching firewall rule */
209
			$filterent = array();
210
			$filterent['interface'] = $_POST['interface'];
211
			$filterent['protocol'] = $_POST['proto'];
212
			$filterent['source']['any'] = "";
213
			$filterent['destination']['address'] = $_POST['localip'];
214

    
215
			$dstpfrom = $_POST['localbeginport'];
216
			$dstpto = $dstpfrom + $_POST['endport'] - $_POST['beginport'];
217

    
218
			if ($dstpfrom == $dstpto)
219
				$filterent['destination']['port'] = $dstpfrom;
220
			else
221
				$filterent['destination']['port'] = $dstpfrom . "-" . $dstpto;
222

    
223
			$filterent['descr'] = "NAT " . $_POST['descr'];
224
			/*
225
			 * Our firewall filter description may be no longer than
226
			 * 63 characters, so don't let it be.
227
			 */
228
			$filterent['descr'] = substr("NAT " . $_POST['descr'], 0, 59);
229

    
230
			$config['filter']['rule'][] = $filterent;
231

    
232
			/*    auto add rule to external port 21 as well since we are using
233
			 *    pftpx to help open up ports automatically
234
			 */
235
			if($_POST['endport'] == "21") {
236
				$filterent = array();
237
				$filterent['interface'] = $_POST['interface'];
238
				$filterent['protocol'] = $_POST['proto'];
239
				$filterent['source']['any'] = "";
240

    
241
				if($_POST['extaddr'] == "") {
242
					$filterent['destination']['network'] = "wanip";
243
				} else {
244
					$filterent['destination']['address'] = $_POST['extaddr'];
245
				}
246

    
247
				$dstpfrom = $_POST['localbeginport'];
248
				$dstpto = $dstpfrom + $_POST['endport'] - $_POST['beginport'];
249

    
250
				if ($dstpfrom == $dstpto)
251
					$filterent['destination']['port'] = $dstpfrom;
252
				else
253
					$filterent['destination']['port'] = $dstpfrom . "-" . $dstpto;
254

    
255
				$filterent['descr'] = "NAT " . $_POST['descr'];
256
				/* See comment above */
257
				$filterent['descr'] = substr("NAT " . $_POST['descr'], 0, 63);
258

    
259
				$config['filter']['rule'][] = $filterent;
260

    
261
				touch($d_filterconfdirty_path);
262

    
263
				write_config();
264

    
265
				header("Location: firewall_nat.php?savemsg=The%20changes%20have%20been%20saved.%20%20Please%20note%20that%20we%20have%20added%20an%20additional%20rule%20for%20the%20FTP%20helper.");
266

    
267
				exit;
268

    
269
			}
270

    
271
			touch($d_filterconfdirty_path);
272
		}
273

    
274
		write_config();
275

    
276
		header("Location: firewall_nat.php");
277
		exit;
278
	}
279
}
280

    
281
$pgtitle = array("Firewall","NAT","Port Forward: Edit");
282
include("head.inc");
283

    
284
?>
285

    
286
<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
287
<?php
288
include("fbegin.inc"); ?>
289
<?php if ($input_errors) print_input_errors($input_errors); ?>
290
            <form action="firewall_nat_edit.php" method="post" name="iform" id="iform">
291
              <table width="100%" border="0" cellpadding="6" cellspacing="0">
292
	  	<tr>
293
                  <td width="22%" valign="top" class="vncellreq">Interface</td>
294
                  <td width="78%" class="vtable">
295
					<select name="interface" class="formselect">
296
						<?php
297
						
298
						$interfaces = array();
299
						
300
						if(have_ruleint_access("lan")) 
301
							$interfaces['lan'] = "LAN";
302
						if(have_ruleint_access("wan")) 
303
							$interfaces['wan'] = "WAN";
304
							
305
						for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) 
306
							if(have_ruleint_access("opt{$i}")) 
307
								$interfaces['opt' . $i] = $config['interfaces']['opt' . $i]['descr'];
308
						
309
						if ($config['pptpd']['mode'] == "server")
310
							if(have_ruleint_access("pptp")) 
311
								$interfaces['pptp'] = "PPTP VPN";
312
						
313
						if ($config['pppoe']['mode'] == "server")
314
							if(have_ruleint_access("pppoe")) 
315
								$interfaces['pppoe'] = "PPPoE VPN";
316
						
317
						/* add ipsec interfaces */
318
						if (isset($config['ipsec']['enable']) || isset($config['ipsec']['mobileclients']['enable']))
319
							if(have_ruleint_access("enc0")) 
320
								$interfaces["enc0"] = "IPsec";						
321

    
322
						foreach ($interfaces as $iface => $ifacename): ?>
323
						<option value="<?=$iface;?>" <?php if ($iface == $pconfig['interface']) echo "selected"; ?>>
324
						<?=htmlspecialchars($ifacename);?>
325
						</option>
326
						<?php endforeach; ?>
327
					</select><br>
328
                     <span class="vexpl">Choose which interface this rule applies to.<br>
329
                     Hint: in most cases, you'll want to use WAN here.</span></td>
330
                </tr>
331
			    <tr>
332
                  <td width="22%" valign="top" class="vncellreq">External address</td>
333
                  <td width="78%" class="vtable">
334
					<select name="extaddr" class="formselect">
335
						<option value="" <?php if (!$pconfig['extaddr']) echo "selected"; ?>>Interface address</option>
336
<?php					if (is_array($config['virtualip']['vip'])):
337
						foreach ($config['virtualip']['vip'] as $sn): ?>
338
						<option value="<?=$sn['subnet'];?>" <?php if ($sn['subnet'] == $pconfig['extaddr']) echo "selected"; ?>><?=htmlspecialchars("{$sn['subnet']} ({$sn['descr']})");?></option>
339
<?php					endforeach;
340
						endif; ?>
341
						<option value="any" <?php if($pconfig['extaddr'] == "any") echo "selected"; ?>>any</option>
342
					</select>
343
					<br />
344
                    <span class="vexpl">
345
					If you want this rule to apply to another IP address than the IP address of the interface chosen above,
346
					select it here (you need to define <a href="firewall_virtual_ip.php">Virtual IP</a> addresses on the first).  Also note that if you are trying to redirect connections on the LAN select the "any" option.</span></td>
347
                </tr>
348
                <tr>
349
                  <td width="22%" valign="top" class="vncellreq">Protocol</td>
350
                  <td width="78%" class="vtable">
351
                    <select name="proto" class="formselect" onChange="proto_change(); check_for_aliases();">
352
                      <?php $protocols = explode(" ", "TCP UDP TCP/UDP GRE ESP"); foreach ($protocols as $proto): ?>
353
                      <option value="<?=strtolower($proto);?>" <?php if (strtolower($proto) == $pconfig['proto']) echo "selected"; ?>><?=htmlspecialchars($proto);?></option>
354
                      <?php endforeach; ?>
355
                    </select> <br> <span class="vexpl">Choose which IP protocol
356
                    this rule should match.<br>
357
                    Hint: in most cases, you should specify <em>TCP</em> &nbsp;here.</span></td>
358
                </tr>
359
                <tr>
360
                  <td width="22%" valign="top" class="vncellreq">External port
361
                    range </td>
362
                  <td width="78%" class="vtable">
363
                    <table border="0" cellspacing="0" cellpadding="0">
364
                      <tr>
365
                        <td>from:&nbsp;&nbsp;</td>
366
                        <td><select name="beginport" class="formselect" onChange="ext_rep_change(); ext_change(); check_for_aliases();">
367
                            <option value="">(other)</option>
368
                            <?php $bfound = 0; foreach ($wkports as $wkport => $wkportdesc): ?>
369
                            <option value="<?=$wkport;?>" <?php if ($wkport == $pconfig['beginport']) {
370
								echo "selected";
371
								$bfound = 1;
372
							}?>>
373
							<?=htmlspecialchars($wkportdesc);?>
374
							</option>
375
                            <?php endforeach; ?>
376
                          </select> <input onChange="check_for_aliases();" autocomplete='off' class="formfldalias" name="beginport_cust" id="beginport_cust" type="text" size="5" value="<?php if (!$bfound) echo $pconfig['beginport']; ?>"></td>
377
                      </tr>
378
                      <tr>
379
                        <td>to:</td>
380
                        <td><select name="endport" class="formselect" onChange="ext_change(); check_for_aliases();">
381
                            <option value="">(other)</option>
382
                            <?php $bfound = 0; foreach ($wkports as $wkport => $wkportdesc): ?>
383
                            <option value="<?=$wkport;?>" <?php if ($wkport == $pconfig['endport']) {
384
								echo "selected";
385
								$bfound = 1;
386
							}?>>
387
							<?=htmlspecialchars($wkportdesc);?>
388
							</option>
389
							<?php endforeach; ?>
390
                          </select> <input onChange="check_for_aliases();" class="formfldalias" autocomplete='off' name="endport_cust" id="endport_cust" type="text" size="5" value="<?php if (!$bfound) echo $pconfig['endport']; ?>"></td>
391
                      </tr>
392
                    </table>
393
                    <br> <span class="vexpl">Specify the port or port range on
394
                    the firewall's external address for this mapping.<br>
395
                    Hint: you can leave the <em>'to'</em> field empty if you only
396
                    want to map a single port</span></td>
397
                </tr>
398
                <tr>
399
                  <td width="22%" valign="top" class="vncellreq">NAT IP</td>
400
                  <td width="78%" class="vtable">
401
                    <input autocomplete='off' name="localip" type="text" class="formfldalias" id="localip" size="20" value="<?=htmlspecialchars($pconfig['localip']);?>">
402
                    <br> <span class="vexpl">Enter the internal IP address of
403
                    the server on which you want to map the ports.<br>
404
                    e.g. <em>192.168.1.12</em></span></td>
405
                </tr>
406
                <tr>
407
                  <td width="22%" valign="top" class="vncellreq">Local port</td>
408
                  <td width="78%" class="vtable">
409
                    <select name="localbeginport" class="formselect" onChange="ext_change();check_for_aliases();">
410
                      <option value="">(other)</option>
411
                      <?php $bfound = 0; foreach ($wkports as $wkport => $wkportdesc): ?>
412
                      <option value="<?=$wkport;?>" <?php if ($wkport == $pconfig['localbeginport']) {
413
							echo "selected";
414
							$bfound = 1;
415
						}?>>
416
					  <?=htmlspecialchars($wkportdesc);?>
417
					  </option>
418
                      <?php endforeach; ?>
419
                    </select> <input onChange="check_for_aliases();" autocomplete='off' class="formfldalias" name="localbeginport_cust" id="localbeginport_cust" type="text" size="5" value="<?php if (!$bfound) echo $pconfig['localbeginport']; ?>">
420
                    <br>
421
                    <span class="vexpl">Specify the port on the machine with the
422
                    IP address entered above. In case of a port range, specify
423
                    the beginning port of the range (the end port will be calculated
424
                    automatically).<br>
425
                    Hint: this is usually identical to the 'from' port above</span></td>
426
                </tr>
427
                <tr>
428
                  <td width="22%" valign="top" class="vncell">Description</td>
429
                  <td width="78%" class="vtable">
430
                    <input name="descr" type="text" class="formfld unknown" id="descr" size="40" value="<?=htmlspecialchars($pconfig['descr']);?>">
431
                    <br> <span class="vexpl">You may enter a description here
432
                    for your reference (not parsed).</span></td>
433
                </tr>
434
				<tr>
435
					<td width="22%" valign="top" class="vncell">No XMLRPC Sync</td>
436
					<td width="78%" class="vtable">
437
						<input type="checkbox" value="yes" name="nosync"<?php if($pconfig['nosync']) echo " CHECKED"; ?>><br>
438
						HINT: This prevents the rule from automatically syncing to other CARP members.
439
					</td>
440
				</tr>
441
                <?php if ((!(isset($id) && $a_nat[$id])) || (isset($_GET['dup']))): ?>
442
                <tr>
443
                  <td width="22%" valign="top">&nbsp;</td>
444
                  <td width="78%">
445
                    <input name="autoadd" type="checkbox" id="autoadd" value="yes" CHECKED>
446
                    <strong>Auto-add a firewall rule to permit traffic through
447
                    this NAT rule</strong></td>
448
                </tr><?php endif; ?>
449
                <tr>
450
                  <td width="22%" valign="top">&nbsp;</td>
451
                  <td width="78%">
452
                    <input name="Submit" type="submit" class="formbtn" value="Save"> <input type="button" class="formbtn" value="Cancel" onclick="history.back()">
453
                    <?php if (isset($id) && $a_nat[$id]): ?>
454
                    <input name="id" type="hidden" value="<?=$id;?>">
455
                    <?php endif; ?>
456
                  </td>
457
                </tr>
458
              </table>
459
</form>
460
<script language="JavaScript">
461
<!--
462
	ext_change();
463
//-->
464
</script>
465
<?php
466
$isfirst = 0;
467
$aliases = "";
468
$addrisfirst = 0;
469
$aliasesaddr = "";
470
if($config['aliases']['alias'] <> "")
471
	foreach($config['aliases']['alias'] as $alias_name) {
472
		if(!stristr($alias_name['address'], ".")) {
473
			if($isfirst == 1) $aliases .= ",";
474
			$aliases .= "'" . $alias_name['name'] . "'";
475
			$isfirst = 1;
476
		} else {
477
			if($addrisfirst == 1) $aliasesaddr .= ",";
478
			$aliasesaddr .= "'" . $alias_name['name'] . "'";
479
			$addrisfirst = 1;
480
		}
481
	}
482
?>
483
<script language="JavaScript">
484
<!--
485
	var addressarray=new Array(<?php echo $aliasesaddr; ?>);
486
	var customarray=new Array(<?php echo $aliases; ?>);
487
//-->
488
</script>
489
<?php include("fend.inc"); ?>
490
</body>
491
</html>
(45-45/189)