Skip to content

Commit 099dbc4

Browse files
author
Jared Hendrickson
committed
Restructured port forward endpoint to be more efficient and organized, added update function to port forward endpoint, updated unit test for port forwards, updated documentation
1 parent dc686c8 commit 099dbc4

10 files changed

Lines changed: 656 additions & 153 deletions

File tree

README.md

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,7 @@ There is no limit to API calls at this time but is important to note that pfSens
513513
* [Create NAT Port Forwards](#1-create-nat-port-forwards)
514514
* [Delete NAT Port Forwards](#2-delete-nat-port-forwards)
515515
* [Read NAT Port Forwards](#3-read-nat-port-forwards)
516+
* [Update NAT Port Forwards](#4-update-nat-port-forwards)
516517

517518
* [FIREWALL/RULE](#firewallrule)
518519

@@ -1044,7 +1045,6 @@ URL: https://{{$hostname}}/api/v1/firewall/nat/port_forward
10441045

10451046
| Key | Value | Description |
10461047
| --- | ------|-------------|
1047-
| type | string | Set a firewall rule type (`pass`, `block`, `reject`) |
10481048
| interface | string | Set which interface the rule will apply to. You may specify either the interface's descriptive name, the pfSense ID (wan, lan, optx), or the physical interface id (e.g. igb0). Floating rules are not supported. |
10491049
| protocol | string | Set which transfer protocol the rule will apply to. If `tcp`, `udp`, `tcp/udp`, you must define a source and destination port |
10501050
| src | string | Set the source address of the firewall rule. This may be a single IP, network CIDR, alias name, or interface. When specifying an interface, you may use the physical interface ID, the descriptive interfance name, or the pfSense ID. To use only interface address, add `ip` to the end of the interface name otherwise the entire interface's subnet is implied. To negate the context of the source address, you may prepend the address with `!` |
@@ -1056,7 +1056,7 @@ URL: https://{{$hostname}}/api/v1/firewall/nat/port_forward
10561056
| natreflection | string | Set the NAT reflection mode explicitly (optional) |
10571057
| descr | string | Set a description for the rule (optional) |
10581058
| disabled | boolean | Disable the rule upon creation (optional) |
1059-
| top | boolean | Add firewall rule to top of access control list (optional) |
1059+
| top | boolean | Add this port forward rule to top of access control list (optional) |
10601060

10611061

10621062

@@ -1146,6 +1146,65 @@ URL: https://{{$hostname}}/api/v1/firewall/nat/port_forward
11461146

11471147

11481148

1149+
### 4. Update NAT Port Forwards
1150+
1151+
1152+
Update an existing port forward rule.<br><br>
1153+
1154+
_Requires at least one of the following privileges:_ [`page-all`, `page-firewall-nat-portforward-edit`]
1155+
1156+
1157+
***Endpoint:***
1158+
1159+
```bash
1160+
Method: PUT
1161+
Type: RAW
1162+
URL: https://{{$hostname}}/api/v1/firewall/nat/port_forward
1163+
```
1164+
1165+
1166+
1167+
***Query params:***
1168+
1169+
| Key | Value | Description |
1170+
| --- | ------|-------------|
1171+
| Id | Integer | Specify the ID of the port forward rule to update. |
1172+
| interface | string | Update the interface the rule will apply to. You may specify either the interface's descriptive name, the pfSense ID (wan, lan, optx), or the physical interface id (e.g. igb0). Floating rules are not supported. (optional) |
1173+
| protocol | string | Update which transfer protocol the rule will apply to. If `tcp`, `udp`, `tcp/udp`, you must define a source and destination port. (optional) |
1174+
| src | string | Update the source address of the firewall rule. This may be a single IP, network CIDR, alias name, or interface. When specifying an interface, you may use the physical interface ID, the descriptive interfance name, or the pfSense ID. To use only interface address, add `ip` to the end of the interface name otherwise the entire interface's subnet is implied. To negate the context of the source address, you may prepend the address with `!` (optional) |
1175+
| dst | string | Update the destination address of the firewall rule. This may be a single IP, network CIDR, alias name, or interface. When specifying an interface, you may use the physical interface ID, the descriptive interface name, or the pfSense ID. To only use interface address, add `ip` to the end of the interface name otherwise the entire interface's subnet is implied. To negate the context of the source address, you may prepend the address with `!` (optional) |
1176+
| srcport | string or integer | Update the TCP and/or UDP source port of the firewall rule. This is only necessary if you have specified the `protocol` to `tcp`, `udp`, `tcp/udp` (optional) |
1177+
| dstport | string or integer | Update the TCP and/or UDP destination port of the firewall rule. This is only necessary if you have specified the `protocol` to `tcp`, `udp`, `tcp/udp` (optional) |
1178+
| target | string | Update the IP to forward traffic to (optional) |
1179+
| local-port | string | Udate the TCP and/or UDP port to forward traffic to. This is only necessary if you have specified the `protocol` to `tcp`, `udp`, `tcp/udp`. Port ranges may be specified using colon or hyphen. (optional) |
1180+
| natreflection | string | Update the NAT reflection mode explicitly (optional) |
1181+
| descr | string | Update a description for the rule (optional) |
1182+
| disabled | boolean | Enable or disable the rule upon creation. True to disable, false to enable (optional) |
1183+
| top | boolean | Move this port forward rule to top of access control list (optional) |
1184+
1185+
1186+
1187+
***Body:***
1188+
1189+
```js
1190+
{
1191+
"interface": "WAN",
1192+
"protocol": "tcp",
1193+
"src": "any",
1194+
"srcport": "433",
1195+
"dst": "em0ip",
1196+
"dstport": "443",
1197+
"target": "192.168.1.123",
1198+
"local-port": "443",
1199+
"natreflection": "purenat",
1200+
"descr": "Forward pb to lc",
1201+
"nosync": true,
1202+
"top": false
1203+
}
1204+
```
1205+
1206+
1207+
11491208
## FIREWALL/RULE
11501209

11511210

docs/documentation.json

Lines changed: 101 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2704,7 +2704,7 @@
27042704
}
27052705
},
27062706
"url": {
2707-
"raw": "https://{{$hostname}}/api/v1/firewall/nat/port_forward?type=string&interface=string&protocol=string&src=string&dst=string&srcport=string or integer&dstport=string or integer&target=string&local-port=string&natreflection=string&descr=string&disabled=boolean&top=boolean",
2707+
"raw": "https://{{$hostname}}/api/v1/firewall/nat/port_forward?interface=string&protocol=string&src=string&dst=string&srcport=string or integer&dstport=string or integer&target=string&local-port=string&natreflection=string&descr=string&disabled=boolean&top=boolean",
27082708
"protocol": "https",
27092709
"host": [
27102710
"{{$hostname}}"
@@ -2717,11 +2717,6 @@
27172717
"port_forward"
27182718
],
27192719
"query": [
2720-
{
2721-
"key": "type",
2722-
"value": "string",
2723-
"description": "Set a firewall rule type (`pass`, `block`, `reject`)"
2724-
},
27252720
{
27262721
"key": "interface",
27272722
"value": "string",
@@ -2780,14 +2775,113 @@
27802775
{
27812776
"key": "top",
27822777
"value": "boolean",
2783-
"description": "Add firewall rule to top of access control list (optional)"
2778+
"description": "Add this port forward rule to top of access control list (optional)"
27842779
}
27852780
]
27862781
},
27872782
"description": "Add a new NAT port forward rule.<br><br>\n\n_Requires at least one of the following privileges:_ [`page-all`, `page-firewall-nat-portforward-edit`]"
27882783
},
27892784
"response": []
27902785
},
2786+
{
2787+
"name": "Update NAT Port Forwards",
2788+
"request": {
2789+
"method": "PUT",
2790+
"header": [],
2791+
"body": {
2792+
"mode": "raw",
2793+
"raw": "{\n\t\"interface\": \"WAN\",\n\t\"protocol\": \"tcp\",\n\t\"src\": \"any\",\n\t\"srcport\": \"433\",\n\t\"dst\": \"em0ip\",\n\t\"dstport\": \"443\",\n\t\"target\": \"192.168.1.123\",\n\t\"local-port\": \"443\",\n\t\"natreflection\": \"purenat\",\n\t\"descr\": \"Forward pb to lc\",\n\t\"nosync\": true,\n\t\"top\": false\n}",
2794+
"options": {
2795+
"raw": {
2796+
"language": "json"
2797+
}
2798+
}
2799+
},
2800+
"url": {
2801+
"raw": "https://{{$hostname}}/api/v1/firewall/nat/port_forward?Id=Integer&interface=string&protocol=string&src=string&dst=string&srcport=string or integer&dstport=string or integer&target=string&local-port=string&natreflection=string&descr=string&disabled=boolean&top=boolean",
2802+
"protocol": "https",
2803+
"host": [
2804+
"{{$hostname}}"
2805+
],
2806+
"path": [
2807+
"api",
2808+
"v1",
2809+
"firewall",
2810+
"nat",
2811+
"port_forward"
2812+
],
2813+
"query": [
2814+
{
2815+
"key": "Id",
2816+
"value": "Integer",
2817+
"description": "Specify the ID of the port forward rule to update."
2818+
},
2819+
{
2820+
"key": "interface",
2821+
"value": "string",
2822+
"description": "Update the interface the rule will apply to. You may specify either the interface's descriptive name, the pfSense ID (wan, lan, optx), or the physical interface id (e.g. igb0). Floating rules are not supported. (optional)"
2823+
},
2824+
{
2825+
"key": "protocol",
2826+
"value": "string",
2827+
"description": "Update which transfer protocol the rule will apply to. If `tcp`, `udp`, `tcp/udp`, you must define a source and destination port. (optional)"
2828+
},
2829+
{
2830+
"key": "src",
2831+
"value": "string",
2832+
"description": "Update the source address of the firewall rule. This may be a single IP, network CIDR, alias name, or interface. When specifying an interface, you may use the physical interface ID, the descriptive interfance name, or the pfSense ID. To use only interface address, add `ip` to the end of the interface name otherwise the entire interface's subnet is implied. To negate the context of the source address, you may prepend the address with `!` (optional)"
2833+
},
2834+
{
2835+
"key": "dst",
2836+
"value": "string",
2837+
"description": "Update the destination address of the firewall rule. This may be a single IP, network CIDR, alias name, or interface. When specifying an interface, you may use the physical interface ID, the descriptive interface name, or the pfSense ID. To only use interface address, add `ip` to the end of the interface name otherwise the entire interface's subnet is implied. To negate the context of the source address, you may prepend the address with `!` (optional)"
2838+
},
2839+
{
2840+
"key": "srcport",
2841+
"value": "string or integer",
2842+
"description": "Update the TCP and/or UDP source port of the firewall rule. This is only necessary if you have specified the `protocol` to `tcp`, `udp`, `tcp/udp` (optional)"
2843+
},
2844+
{
2845+
"key": "dstport",
2846+
"value": "string or integer",
2847+
"description": "Update the TCP and/or UDP destination port of the firewall rule. This is only necessary if you have specified the `protocol` to `tcp`, `udp`, `tcp/udp` (optional)"
2848+
},
2849+
{
2850+
"key": "target",
2851+
"value": "string",
2852+
"description": "Update the IP to forward traffic to (optional)"
2853+
},
2854+
{
2855+
"key": "local-port",
2856+
"value": "string",
2857+
"description": "Udate the TCP and/or UDP port to forward traffic to. This is only necessary if you have specified the `protocol` to `tcp`, `udp`, `tcp/udp`. Port ranges may be specified using colon or hyphen. (optional)"
2858+
},
2859+
{
2860+
"key": "natreflection",
2861+
"value": "string",
2862+
"description": "Update the NAT reflection mode explicitly (optional)"
2863+
},
2864+
{
2865+
"key": "descr",
2866+
"value": "string",
2867+
"description": "Update a description for the rule (optional)"
2868+
},
2869+
{
2870+
"key": "disabled",
2871+
"value": "boolean",
2872+
"description": "Enable or disable the rule upon creation. True to disable, false to enable (optional)"
2873+
},
2874+
{
2875+
"key": "top",
2876+
"value": "boolean",
2877+
"description": "Move this port forward rule to top of access control list (optional)"
2878+
}
2879+
]
2880+
},
2881+
"description": "Update an existing port forward rule.<br><br>\n\n_Requires at least one of the following privileges:_ [`page-all`, `page-firewall-nat-portforward-edit`]"
2882+
},
2883+
"response": []
2884+
},
27912885
{
27922886
"name": "Delete NAT Port Forwards",
27932887
"request": {

pfSense-pkg-API/files/etc/inc/api/endpoints/APIFirewallNATPortForward.inc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ class APIFirewallNATPortForward extends APIEndpoint {
2828
return (new APIFirewallNATPortForwardCreate())->call();
2929
}
3030

31+
protected function put() {
32+
return (new APIFirewallNATPortForwardUpdate())->call();
33+
}
34+
3135
protected function delete() {
3236
return (new APIFirewallNATPortForwardDelete())->call();
3337
}

pfSense-pkg-API/files/etc/inc/api/framework/APITools.inc

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -287,30 +287,25 @@ function enable_carp($enable) {
287287
}
288288

289289
// Sorts nat rules by specified criteria and reloads the filter
290-
function sort_nat_rules($mode=null, $data=null) {
290+
function sort_nat_rules($top=false, $data=null) {
291291
// Variables
292292
global $config;
293293
$sort_arr = [];
294-
$master_arr = [];
295-
foreach ($config["nat"]["rule"] as $idx => $fre) {
296-
$curr_iface = $fre["interface"]; // Save our current entries interface
297-
// Create our interface array if does not exist
298-
if (!isset($sort_arr[$curr_iface])) {
299-
$sort_arr[$curr_iface] = [];
300-
}
301-
// Check if user requested this rule to be placed at the top of array
302-
if ($mode === "top" and $idx === $data) {
303-
array_unshift($sort_arr[$curr_iface], $fre);
294+
$rules = (array_key_exists(0, $config["nat"]["rule"])) ? $config["nat"]["rule"] : [$config["nat"]["rule"]];
295+
296+
foreach ($rules as $idx => $fre) {
297+
# Check if top mode is enabled, if so add this item to the start of the array
298+
if ($top === true and $idx === $data) {
299+
array_unshift($sort_arr, $fre);
304300
} else {
305-
$sort_arr[$curr_iface][] = $fre;
301+
$sort_arr[] = $fre;
306302
}
307303
}
308-
foreach ($sort_arr as $if) {
309-
foreach ($if as $rule) {
310-
$master_arr[] = $rule;
311-
}
304+
if (!empty($config["nat"]["rule"])) {
305+
$config["nat"]["rule"] = $sort_arr;
306+
} else {
307+
unset($config["nat"]["rule"]);
312308
}
313-
$config["nat"]["rule"] = $master_arr;
314309
}
315310

316311
# Input a physical interface ID, or a descriptive interface name, and return the pfSense interface ID (lan,wan,optx)

0 commit comments

Comments
 (0)