Project

General

Profile

Download (19.4 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
						$iflist = get_configured_interface_with_descr(false, true);
299
						foreach ($iflist as $if => $ifdesc) 
300
							if(have_ruleint_access($if)) 
301
								$interfaces[$if] = $ifdesc;
302
						
303
						if ($config['pptpd']['mode'] == "server")
304
							if(have_ruleint_access("pptp")) 
305
								$interfaces['pptp'] = "PPTP VPN";
306
						
307
						if ($config['pppoe']['mode'] == "server")
308
							if(have_ruleint_access("pppoe")) 
309
								$interfaces['pppoe'] = "PPPoE VPN";
310
						
311
						/* add ipsec interfaces */
312
						if (isset($config['ipsec']['enable']) || isset($config['ipsec']['mobileclients']['enable']))
313
							if(have_ruleint_access("enc0")) 
314
								$interfaces["enc0"] = "IPsec";						
315

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