From 182bb2e4fedb5e1fcf0bf7ddef42f15c16cb32ee Mon Sep 17 00:00:00 2001
From: MrClayPole <9336574+MrClayPole@users.noreply.github.com>
Date: Wed, 8 Jul 2026 09:21:00 +0100
Subject: [PATCH 1/2] net/shadowsocks: add explicit outbound blocklist
Add optional ssserver outbound ACL generation using user-specified IPv4 and IPv6 destination blocklists. The generated ACL intentionally has no default private/reserved ranges so administrators choose the exact destinations to block.
---
net/shadowsocks/Makefile | 2 +-
.../OPNsense/Shadowsocks/forms/general.xml | 19 ++++++++++++
.../models/OPNsense/Shadowsocks/General.xml | 16 +++++++++-
.../templates/OPNsense/Shadowsocks/+TARGETS | 1 +
.../OPNsense/Shadowsocks/config.json | 3 +-
.../templates/OPNsense/Shadowsocks/server.acl | 31 +++++++++++++++++++
6 files changed, 69 insertions(+), 3 deletions(-)
create mode 100644 net/shadowsocks/src/opnsense/service/templates/OPNsense/Shadowsocks/server.acl
diff --git a/net/shadowsocks/Makefile b/net/shadowsocks/Makefile
index 34945a08ca..15f9cdfc7f 100644
--- a/net/shadowsocks/Makefile
+++ b/net/shadowsocks/Makefile
@@ -1,5 +1,5 @@
PLUGIN_NAME= shadowsocks
-PLUGIN_VERSION= 1.3
+PLUGIN_VERSION= 1.4
PLUGIN_COMMENT= Secure socks5 proxy
PLUGIN_DEPENDS= shadowsocks-rust
PLUGIN_MAINTAINER= m.muenz@gmail.com
diff --git a/net/shadowsocks/src/opnsense/mvc/app/controllers/OPNsense/Shadowsocks/forms/general.xml b/net/shadowsocks/src/opnsense/mvc/app/controllers/OPNsense/Shadowsocks/forms/general.xml
index 185decc5aa..f5edd92f0e 100644
--- a/net/shadowsocks/src/opnsense/mvc/app/controllers/OPNsense/Shadowsocks/forms/general.xml
+++ b/net/shadowsocks/src/opnsense/mvc/app/controllers/OPNsense/Shadowsocks/forms/general.xml
@@ -54,4 +54,23 @@
checkbox
Allow IP fragmentation on the outbound UDP socket.
+
+
+ general.outbound_blocklist_enabled
+
+ checkbox
+ Generate a Shadowsocks server ACL using [outbound_block_list]. This blocks destinations after sslocal has proxied traffic into this server. Add only the destinations you want to block below.
+
+
+ general.outbound_blocklist_ipv4
+
+ text
+ Comma separated IPv4 addresses or CIDR networks to block, for example 172.28.0.0/16,10.1.0.0/16,10.152.183.0/24.
+
+
+ general.outbound_blocklist_ipv6
+
+ text
+ Comma separated IPv6 addresses or CIDR networks to block, for example fd01::/108,fd98::/108,2a02:8010:6538::/48.
+
diff --git a/net/shadowsocks/src/opnsense/mvc/app/models/OPNsense/Shadowsocks/General.xml b/net/shadowsocks/src/opnsense/mvc/app/models/OPNsense/Shadowsocks/General.xml
index 6819ff0986..7d7ab3ce0c 100644
--- a/net/shadowsocks/src/opnsense/mvc/app/models/OPNsense/Shadowsocks/General.xml
+++ b/net/shadowsocks/src/opnsense/mvc/app/models/OPNsense/Shadowsocks/General.xml
@@ -1,7 +1,7 @@
//OPNsense/shadowsocks/general
Shadowsocks configuration
- 1.0.2
+ 1.0.3
0
@@ -71,5 +71,19 @@
0
Y
+
+ 0
+ Y
+
+
+ N
+ /^([0-9\.\/ ]*?,)*([0-9\.\/ ]*)$/
+ Please provide a comma separated list of IPv4 addresses or CIDR networks.
+
+
+ N
+ /^([a-fA-F0-9\.:\[\]\/ ]*?,)*([a-fA-F0-9\.:\[\]\/ ]*)$/
+ Please provide a comma separated list of IPv6 addresses or CIDR networks.
+
diff --git a/net/shadowsocks/src/opnsense/service/templates/OPNsense/Shadowsocks/+TARGETS b/net/shadowsocks/src/opnsense/service/templates/OPNsense/Shadowsocks/+TARGETS
index bb1f9c5e44..40f7119583 100644
--- a/net/shadowsocks/src/opnsense/service/templates/OPNsense/Shadowsocks/+TARGETS
+++ b/net/shadowsocks/src/opnsense/service/templates/OPNsense/Shadowsocks/+TARGETS
@@ -2,3 +2,4 @@ ssserver:/etc/rc.conf.d/ssserver_rust
config.json:/usr/local/etc/shadowsocks-rust/config.json
sslocal:/etc/rc.conf.d/sslocal_rust
local.json:/usr/local/etc/shadowsocks-rust/local.json
+server.acl:/usr/local/etc/shadowsocks-rust/server.acl
diff --git a/net/shadowsocks/src/opnsense/service/templates/OPNsense/Shadowsocks/config.json b/net/shadowsocks/src/opnsense/service/templates/OPNsense/Shadowsocks/config.json
index 09062d237f..a5fcc0438f 100644
--- a/net/shadowsocks/src/opnsense/service/templates/OPNsense/Shadowsocks/config.json
+++ b/net/shadowsocks/src/opnsense/service/templates/OPNsense/Shadowsocks/config.json
@@ -7,6 +7,7 @@
"timeout":{{ OPNsense.shadowsocks.general.timeout }},
"mode":"{{ OPNsense.shadowsocks.general.tcpudpmode }}",
"method":"{{ OPNsense.shadowsocks.general.cipher }}",
- "outbound_udp_allow_fragmentation":{{ "true" if OPNsense.shadowsocks.general.fragmentation == '1' else "false"}}
+ "outbound_udp_allow_fragmentation":{{ "true" if OPNsense.shadowsocks.general.fragmentation == '1' else "false"}}{% if helpers.exists('OPNsense.shadowsocks.general.outbound_blocklist_enabled') and OPNsense.shadowsocks.general.outbound_blocklist_enabled == '1' %},
+ "acl":"/usr/local/etc/shadowsocks-rust/server.acl"{% endif %}
}
{% endif %}
diff --git a/net/shadowsocks/src/opnsense/service/templates/OPNsense/Shadowsocks/server.acl b/net/shadowsocks/src/opnsense/service/templates/OPNsense/Shadowsocks/server.acl
new file mode 100644
index 0000000000..0388ccf2a8
--- /dev/null
+++ b/net/shadowsocks/src/opnsense/service/templates/OPNsense/Shadowsocks/server.acl
@@ -0,0 +1,31 @@
+{% if helpers.exists('OPNsense.shadowsocks.general.enabled') and OPNsense.shadowsocks.general.enabled == '1' and helpers.exists('OPNsense.shadowsocks.general.outbound_blocklist_enabled') and OPNsense.shadowsocks.general.outbound_blocklist_enabled == '1' %}
+# Generated by OPNsense os-shadowsocks.
+# Applies to ssserver only. sslocal ACLs route/proxy/bypass; they do not block.
+# Only user-specified destinations are emitted here; no default private/reserved ranges.
+
+[accept_all]
+
+[outbound_allow_all]
+
+[outbound_block_list]
+{% if helpers.exists('OPNsense.shadowsocks.general.outbound_blocklist_ipv4') and OPNsense.shadowsocks.general.outbound_blocklist_ipv4 != '' %}
+
+# User IPv4 blocklist
+{% for item in OPNsense.shadowsocks.general.outbound_blocklist_ipv4.split(',') %}
+{% set entry = item.strip() %}
+{% if entry != '' %}
+{{ entry }}
+{% endif %}
+{% endfor %}
+{% endif %}
+{% if helpers.exists('OPNsense.shadowsocks.general.outbound_blocklist_ipv6') and OPNsense.shadowsocks.general.outbound_blocklist_ipv6 != '' %}
+
+# User IPv6 blocklist
+{% for item in OPNsense.shadowsocks.general.outbound_blocklist_ipv6.split(',') %}
+{% set entry = item.strip() %}
+{% if entry != '' %}
+{{ entry }}
+{% endif %}
+{% endfor %}
+{% endif %}
+{% endif %}
From b27196d63dbab0ec0fa4831a4b7cd502b6211d2d Mon Sep 17 00:00:00 2001
From: MrClayPole <9336574+MrClayPole@users.noreply.github.com>
Date: Wed, 8 Jul 2026 10:35:35 +0100
Subject: [PATCH 2/2] net/shadowsocks: keep blocklist inputs as text fields
Use TextField for the comma-separated outbound IPv4 and IPv6 blocklist inputs so values round-trip through the text form instead of being treated as list widget data.
---
.../opnsense/mvc/app/models/OPNsense/Shadowsocks/General.xml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/shadowsocks/src/opnsense/mvc/app/models/OPNsense/Shadowsocks/General.xml b/net/shadowsocks/src/opnsense/mvc/app/models/OPNsense/Shadowsocks/General.xml
index 7d7ab3ce0c..700e594579 100644
--- a/net/shadowsocks/src/opnsense/mvc/app/models/OPNsense/Shadowsocks/General.xml
+++ b/net/shadowsocks/src/opnsense/mvc/app/models/OPNsense/Shadowsocks/General.xml
@@ -75,12 +75,12 @@
0
Y
-
+
N
/^([0-9\.\/ ]*?,)*([0-9\.\/ ]*)$/
Please provide a comma separated list of IPv4 addresses or CIDR networks.
-
+
N
/^([a-fA-F0-9\.:\[\]\/ ]*?,)*([a-fA-F0-9\.:\[\]\/ ]*)$/
Please provide a comma separated list of IPv6 addresses or CIDR networks.