Project

General

Profile

Download (20.5 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
	pfSense_MODULE:	nat
33
*/
34

    
35
##|+PRIV
36
##|*IDENT=page-firewall-nat-portforward-edit
37
##|*NAME=Firewall: NAT: Port Forward: Edit page
38
##|*DESCR=Allow access to the 'Firewall: NAT: Port Forward: Edit' page.
39
##|*MATCH=firewall_nat_edit.php*
40
##|-PRIV
41

    
42
require("guiconfig.inc");
43

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

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

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

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

    
74
if (isset($_GET['dup']))
75
	unset($id);
76

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

    
87
if ($_POST) {
88

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

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

    
102
	unset($input_errors);
103
	$pconfig = $_POST;
104

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

    
114
	do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors);
115

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

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

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

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

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

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

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

    
147
	}
148

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

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

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

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

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

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

    
183
		$natent['target'] = $_POST['localip'];
184
		$natent['local-port'] = $_POST['localbeginport'];
185
		$natent['interface'] = $_POST['interface'];
186
		$natent['descr'] = $_POST['descr'];
187
		$natent['associated-filter-rule-id'] = $_POST['associated-filter-rule-id'];
188

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

    
194
		$need_filter_rule = false;
195
		// Updating a rule with a filter rule associated
196
		if( $natent['associated-filter-rule-id']>0 )
197
			$need_filter_rule = true;
198
		// If creating a new rule, where we want to add the filter rule, associated or not
199
		else if( isset($_POST['filter-rule-association']) && 
200
			($_POST['filter-rule-association']=='add-associated' || 
201
			$_POST['filter-rule-association']=='add-unassociated') )
202
			$need_filter_rule = true;
203

    
204
		if ($need_filter_rule) {
205

    
206
			// If we had a previous rule associated with this NAT rule, delete that
207
			if( $natent['associated-filter-rule-id'] > 0 )
208
				delete_id($natent['associated-filter-rule-id'], $config['filter']['rule']);
209

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

    
217
			$dstpfrom = $_POST['localbeginport'];
218
			$dstpto = $dstpfrom + $_POST['endport'] - $_POST['beginport'];
219

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

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

    
232
			// If we had a previous rule association, update this rule with that ID so we don't lose association
233
			if ($natent['associated-filter-rule-id'] > 0)
234
				$filterent['id'] = $natent['associated-filter-rule-id']; 
235
			// If we wanted this rule to be associated, make sure the NAT entry is updated with the same ID
236
			else if($_POST['filter-rule-association']=='add-associated')
237
				$natent['associated-filter-rule-id'] = $filterent['id'] = get_next_id($config['filter']['rule']);
238

    
239
			$config['filter']['rule'][] = $filterent;
240

    
241
			mark_subsystem_dirty('filter');
242
		}
243

    
244
		// Update NAT entry after creating/updating the firewall rule, so we have it's rule ID if one was created
245
		if (isset($id) && $a_nat[$id])
246
			$a_nat[$id] = $natent;
247
		else {
248
			if (is_numeric($after))
249
				array_splice($a_nat, $after+1, 0, array($natent));
250
			else
251
				$a_nat[] = $natent;
252
		}
253

    
254
		mark_subsystem_dirty('natconf');
255

    
256
		write_config();
257

    
258
		header("Location: firewall_nat.php");
259
		exit;
260
	}
261
}
262

    
263
$pgtitle = array("Firewall","NAT","Port Forward: Edit");
264
include("head.inc");
265

    
266
?>
267

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

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