Project

General

Profile

Download (19.3 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
##|+PRIV
33
##|*IDENT=page-firewall-nat-portforward-edit
34
##|*NAME=Firewall: NAT: Port Forward: Edit page
35
##|*DESCR=Allow access to the 'Firewall: NAT: Port Forward: Edit' page.
36
##|*MATCH=firewall_nat_edit.php*
37
##|-PRIV
38

    
39

    
40
require("guiconfig.inc");
41

    
42
if (!is_array($config['nat']['rule'])) {
43
	$config['nat']['rule'] = array();
44
}
45
//nat_rules_sort();
46
$a_nat = &$config['nat']['rule'];
47

    
48
$id = $_GET['id'];
49
if (isset($_POST['id']))
50
	$id = $_POST['id'];
51

    
52
if (isset($_GET['dup'])) {
53
        $id = $_GET['dup'];
54
        $after = $_GET['dup'];
55
}
56

    
57
if (isset($id) && $a_nat[$id]) {
58
	$pconfig['extaddr'] = $a_nat[$id]['external-address'];
59
	$pconfig['proto'] = $a_nat[$id]['protocol'];
60
	list($pconfig['beginport'],$pconfig['endport']) = explode("-", $a_nat[$id]['external-port']);
61
	$pconfig['localip'] = $a_nat[$id]['target'];
62
	$pconfig['localbeginport'] = $a_nat[$id]['local-port'];
63
	$pconfig['descr'] = $a_nat[$id]['descr'];
64
	$pconfig['interface'] = $a_nat[$id]['interface'];
65
	$pconfig['nosync'] = isset($a_nat[$id]['nosync']);
66
	if (!$pconfig['interface'])
67
		$pconfig['interface'] = "wan";
68
} else {
69
	$pconfig['interface'] = "wan";
70
}
71

    
72
if (isset($_GET['dup']))
73
	unset($id);
74

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

    
85
if ($_POST) {
86

    
87
	if ($_POST['beginport_cust'] && !$_POST['beginport'])
88
		$_POST['beginport'] = $_POST['beginport_cust'];
89
	if ($_POST['endport_cust'] && !$_POST['endport'])
90
		$_POST['endport'] = $_POST['endport_cust'];
91
	if ($_POST['localbeginport_cust'] && !$_POST['localbeginport'])
92
		$_POST['localbeginport'] = $_POST['localbeginport_cust'];
93

    
94
	if (!$_POST['endport'])
95
		$_POST['endport'] = $_POST['beginport'];
96
        /* Make beginning port end port if not defined and endport is */
97
        if (!$_POST['beginport'] && $_POST['endport'])
98
                $_POST['beginport'] = $_POST['endport'];
99

    
100
	unset($input_errors);
101
	$pconfig = $_POST;
102

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

    
112
	do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
113

    
114
	if (($_POST['localip'] && !is_ipaddroralias($_POST['localip']))) {
115
		$input_errors[] = "\"{$_POST['localip']}\" is not valid NAT IP address or host alias.";
116
	}
117

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

    
121
		if (($_POST['beginport'] && !is_ipaddroralias($_POST['beginport']) && !is_port($_POST['beginport']))) {
122
			$input_errors[] = "The start port must be an integer between 1 and 65535.";
123
		}
124

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

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

    
133
		if ($_POST['beginport'] > $_POST['endport']) {
134
			/* swap */
135
			$tmp = $_POST['endport'];
136
			$_POST['endport'] = $_POST['beginport'];
137
			$_POST['beginport'] = $tmp;
138
		}
139

    
140
		if (!$input_errors) {
141
			if (($_POST['endport'] - $_POST['beginport'] + $_POST['localbeginport']) > 65535)
142
				$input_errors[] = "The target port range must be an integer between 1 and 65535.";
143
		}
144

    
145
	}
146

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

    
158
		list($begp,$endp) = explode("-", $natent['external-port']);
159
		if (!$endp)
160
			$endp = $begp;
161

    
162
		if (!(   (($_POST['beginport'] < $begp) && ($_POST['endport'] < $begp))
163
		      || (($_POST['beginport'] > $endp) && ($_POST['endport'] > $endp)))) {
164

    
165
			$input_errors[] = "The external port range overlaps with an existing entry.";
166
			break;
167
		}
168
	}
169

    
170
	if (!$input_errors) {
171
		$natent = array();
172
		if ($_POST['extaddr'])
173
			$natent['external-address'] = $_POST['extaddr'];
174
		$natent['protocol'] = $_POST['proto'];
175

    
176
		if ($_POST['beginport'] == $_POST['endport'])
177
			$natent['external-port'] = $_POST['beginport'];
178
		else
179
			$natent['external-port'] = $_POST['beginport'] . "-" . $_POST['endport'];
180

    
181
		$natent['target'] = $_POST['localip'];
182
		$natent['local-port'] = $_POST['localbeginport'];
183
		$natent['interface'] = $_POST['interface'];
184
		$natent['descr'] = $_POST['descr'];
185

    
186
		if($_POST['nosync'] == "yes")
187
			$natent['nosync'] = true;
188
		else
189
			unset($natent['nosync']);
190

    
191
		if (isset($id) && $a_nat[$id])
192
			$a_nat[$id] = $natent;
193
		else {
194
			if (is_numeric($after))
195
				array_splice($a_nat, $after+1, 0, array($natent));
196
			else
197
				$a_nat[] = $natent;
198
		}
199

    
200
		touch($d_natconfdirty_path);
201

    
202
		if ($_POST['autoadd']) {
203
			/* auto-generate a matching firewall rule */
204
			$filterent = array();
205
			$filterent['interface'] = $_POST['interface'];
206
			$filterent['protocol'] = $_POST['proto'];
207
			$filterent['source']['any'] = "";
208
			$filterent['destination']['address'] = $_POST['localip'];
209

    
210
			$dstpfrom = $_POST['localbeginport'];
211
			$dstpto = $dstpfrom + $_POST['endport'] - $_POST['beginport'];
212

    
213
			if ($dstpfrom == $dstpto)
214
				$filterent['destination']['port'] = $dstpfrom;
215
			else
216
				$filterent['destination']['port'] = $dstpfrom . "-" . $dstpto;
217

    
218
			$filterent['descr'] = "NAT " . $_POST['descr'];
219
			/*
220
			 * Our firewall filter description may be no longer than
221
			 * 63 characters, so don't let it be.
222
			 */
223
			$filterent['descr'] = substr("NAT " . $_POST['descr'], 0, 59);
224

    
225
			$config['filter']['rule'][] = $filterent;
226

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

    
236
				if($_POST['extaddr'] == "") {
237
					$filterent['destination']['network'] = "wanip";
238
				} else {
239
					$filterent['destination']['address'] = $_POST['extaddr'];
240
				}
241

    
242
				$dstpfrom = $_POST['localbeginport'];
243
				$dstpto = $dstpfrom + $_POST['endport'] - $_POST['beginport'];
244

    
245
				if ($dstpfrom == $dstpto)
246
					$filterent['destination']['port'] = $dstpfrom;
247
				else
248
					$filterent['destination']['port'] = $dstpfrom . "-" . $dstpto;
249

    
250
				$filterent['descr'] = "NAT " . $_POST['descr'];
251
				/* See comment above */
252
				$filterent['descr'] = substr("NAT " . $_POST['descr'], 0, 63);
253

    
254
				$config['filter']['rule'][] = $filterent;
255

    
256
				touch($d_filterconfdirty_path);
257

    
258
				write_config();
259

    
260
				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.");
261

    
262
				exit;
263

    
264
			}
265

    
266
			touch($d_filterconfdirty_path);
267
		}
268

    
269
		write_config();
270

    
271
		header("Location: firewall_nat.php");
272
		exit;
273
	}
274
}
275

    
276
$pgtitle = array("Firewall","NAT","Port Forward: Edit");
277
include("head.inc");
278

    
279
?>
280

    
281
<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
282
<?php
283
include("fbegin.inc"); ?>
284
<?php if ($input_errors) print_input_errors($input_errors); ?>
285
            <form action="firewall_nat_edit.php" method="post" name="iform" id="iform">
286
              <table width="100%" border="0" cellpadding="6" cellspacing="0">
287
				<tr>
288
					<td colspan="2" valign="top" class="listtopic">Edit NAT entry</td>
289
				</tr>	
290
				<tr>
291
                  <td width="22%" valign="top" class="vncellreq">Interface</td>
292
                  <td width="78%" class="vtable">
293
					<select name="interface" class="formselect">
294
						<?php
295
						
296
						$iflist = get_configured_interface_with_descr(false, true);
297
						foreach ($iflist as $if => $ifdesc) 
298
							if(have_ruleint_access($if)) 
299
								$interfaces[$if] = $ifdesc;
300
						
301
						if ($config['pptpd']['mode'] == "server")
302
							if(have_ruleint_access("pptp")) 
303
								$interfaces['pptp'] = "PPTP VPN";
304
						
305
						if ($config['pppoe']['mode'] == "server")
306
							if(have_ruleint_access("pppoe")) 
307
								$interfaces['pppoe'] = "PPPoE VPN";
308
						
309
						/* add ipsec interfaces */
310
						if (isset($config['ipsec']['enable']) || isset($config['ipsec']['mobileclients']['enable']))
311
							if(have_ruleint_access("enc0")) 
312
								$interfaces["enc0"] = "IPsec";						
313

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