Project

General

Profile

Download (18.1 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
			touch($d_filterconfdirty_path);
228
		}
229

    
230
		write_config();
231

    
232
		header("Location: firewall_nat.php");
233
		exit;
234
	}
235
}
236

    
237
$pgtitle = array("Firewall","NAT","Port Forward: Edit");
238
include("head.inc");
239

    
240
?>
241

    
242
<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
243
<?php
244
include("fbegin.inc"); ?>
245
<?php if ($input_errors) print_input_errors($input_errors); ?>
246
            <form action="firewall_nat_edit.php" method="post" name="iform" id="iform">
247
              <table width="100%" border="0" cellpadding="6" cellspacing="0">
248
				<tr>
249
					<td colspan="2" valign="top" class="listtopic">Edit NAT entry</td>
250
				</tr>	
251
				<tr>
252
                  <td width="22%" valign="top" class="vncellreq">Interface</td>
253
                  <td width="78%" class="vtable">
254
					<select name="interface" class="formselect">
255
						<?php
256
						
257
						$iflist = get_configured_interface_with_descr(false, true);
258
						foreach ($iflist as $if => $ifdesc) 
259
							if(have_ruleint_access($if)) 
260
								$interfaces[$if] = $ifdesc;
261
						
262
						if ($config['pptpd']['mode'] == "server")
263
							if(have_ruleint_access("pptp")) 
264
								$interfaces['pptp'] = "PPTP VPN";
265
						
266
						if ($config['pppoe']['mode'] == "server")
267
							if(have_ruleint_access("pppoe")) 
268
								$interfaces['pppoe'] = "PPPoE VPN";
269
						
270
						/* add ipsec interfaces */
271
						if (isset($config['ipsec']['enable']) || isset($config['ipsec']['mobileclients']['enable']))
272
							if(have_ruleint_access("enc0")) 
273
								$interfaces["enc0"] = "IPsec";						
274

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