💐 Sync 2025-11-05 00:13:10

This commit is contained in:
actions-user
2025-11-05 00:13:10 +08:00
parent 251207fb9c
commit e112520fb4
24 changed files with 4104 additions and 3316 deletions

View File

@@ -5,6 +5,9 @@
[ $(uname -m) = "x86_64" ] && alias board_name="echo x86_64"
# OTA
OTA_URL="https://api.kejizero.xyz/openwrt/ota.json"
# theme
if [ -d "/www/luci-static/argon" ] && [ -z "$(uci -q get luci.main.pollinterval)" ]; then
uci set luci.main.mediaurlbase='/luci-static/argon'
@@ -94,17 +97,17 @@ devices_setup()
sed -i '/openwrt_core/d' /etc/opkg/distfeeds.conf
sed -i "\$a\src/gz openwrt_core https://core.kejizero.xyz/aarch64_generic/$(grep Version /usr/lib/opkg/info/kernel.control | awk '{print $2}')" /etc/opkg/distfeeds.conf
}
uci set ota.config.api_url="https://api.kejizero.xyz/openwrt/rockchip.json"
uci set ota.config.api_url="$OTA_URL"
uci commit ota
;;
x86_64)
[ $(uname -r | awk -F. '{print $1}') = 6 ] && {
[ -f /sys/kernel/btf/vmlinux ] && [ ! -d "/usr/share/openwrt_core" ] && {
sed -i '/openwrt_core/d' /etc/opkg/distfeeds.conf
sed -i "\$a\src/gz openwrt_core https://core.kejizero.xyz/x86_64/${openwrt_core}/$(grep Version /usr/lib/opkg/info/kernel.control | awk '{print $2}')" /etc/opkg/distfeeds.conf
sed -i "\$a\src/gz openwrt_core https://core.kejizero.xyz/x86_64/$(grep Version /usr/lib/opkg/info/kernel.control | awk '{print $2}')" /etc/opkg/distfeeds.conf
}
}
uci set ota.config.api_url="https://api.kejizero.xyz/openwrt/x86_64.json"
uci set ota.config.api_url="$OTA_URL"
uci commit ota
;;
esac

View File

@@ -10,7 +10,7 @@ LUCI_DEPENDS:=+luci-base +luci-lib-jsonc +curl +bandix
PKG_MAINTAINER:=timsaya
PKG_VERSION:=0.6.2
PKG_VERSION:=0.6.3
PKG_RELEASE:=1
include $(TOPDIR)/feeds/luci/luci.mk

View File

@@ -371,7 +371,7 @@ return view.extend({
var style = E('style', {}, `
.bandix-connection-container {
margin: 0;
padding: 24px;
padding: 8px;
background-color: ${darkMode ? '#1E1E1E' : '#f8fafc'};
min-height: calc(100vh - 100px);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;

View File

@@ -25,6 +25,7 @@ const translations = {
'界面语言': '界面语言',
'选择 Bandix 流量监控的显示语言': '选择 Bandix 流量监控的显示语言',
'设备信息': '设备信息',
'设备列表': '设备列表',
'LAN 流量': 'LAN 流量',
'WAN 流量': 'WAN 流量',
'限速设置': '限速设置',
@@ -103,7 +104,9 @@ const translations = {
'升序': '升序',
'降序': '降序',
'按速度排序': '按速度排序',
'按用量排序': '按用量排序'
'按用量排序': '按用量排序',
'简易模式': '简易模式',
'详细模式': '详细模式'
},
'zh-tw': {
'Bandix 流量监控': 'Bandix 流量監控',
@@ -122,6 +125,7 @@ const translations = {
'界面语言': '介面語言',
'选择 Bandix 流量监控的显示语言': '選擇 Bandix 流量監控的顯示語言',
'设备信息': '設備資訊',
'设备列表': '設備列表',
'LAN 流量': '局域網流量',
'WAN 流量': '跨網路流量',
'限速设置': '限速設定',
@@ -200,7 +204,9 @@ const translations = {
'升序': '升序',
'降序': '降序',
'按速度排序': '按速度排序',
'按用量排序': '按用量排序'
'按用量排序': '按用量排序',
'简易模式': '簡易模式',
'详细模式': '詳細模式'
},
'en': {
'Bandix 流量监控': 'Bandix Traffic Monitor',
@@ -219,6 +225,7 @@ const translations = {
'界面语言': 'Interface Language',
'选择 Bandix 流量监控的显示语言': 'Select the display language for Bandix Traffic Monitor',
'设备信息': 'Device Info',
'设备列表': 'Device List',
'LAN 流量': 'LAN Traffic',
'WAN 流量': 'WAN Traffic',
'限速设置': 'Rate Limit',
@@ -297,7 +304,9 @@ const translations = {
'升序': 'Ascending',
'降序': 'Descending',
'按速度排序': 'Sort by Speed',
'按用量排序': 'Sort by Traffic'
'按用量排序': 'Sort by Traffic',
'简易模式': 'Simple Mode',
'详细模式': 'Detailed Mode'
},
'fr': {
'Bandix 流量监控': 'Moniteur de Trafic Bandix',
@@ -316,6 +325,7 @@ const translations = {
'界面语言': 'Langue de l\'interface',
'选择 Bandix 流量监控的显示语言': 'Sélectionner la langue d\'affichage pour le Moniteur de Trafic Bandix',
'设备信息': 'Informations sur l\'appareil',
'设备列表': 'Liste des appareils',
'LAN 流量': 'Trafic LAN',
'WAN 流量': 'Trafic WAN',
'限速设置': 'Limitation de débit',
@@ -389,7 +399,9 @@ const translations = {
'升序': 'Croissant',
'降序': 'Décroissant',
'按速度排序': 'Trier par vitesse',
'按用量排序': 'Trier par volume'
'按用量排序': 'Trier par volume',
'简易模式': 'Mode simple',
'详细模式': 'Mode détaillé'
},
'ja': {
'Bandix 流量监控': 'Bandix トラフィックモニター',
@@ -408,6 +420,7 @@ const translations = {
'界面语言': 'インターフェース言語',
'选择 Bandix 流量监控的显示语言': 'Bandix トラフィックモニターの表示言語を選択',
'设备信息': 'デバイス情報',
'设备列表': 'デバイスリスト',
'LAN 流量': 'LAN トラフィック',
'WAN 流量': 'WAN トラフィック',
'限速设置': '速度制限',
@@ -481,7 +494,9 @@ const translations = {
'升序': '昇順',
'降序': '降順',
'按速度排序': '速度順',
'按用量排序': '使用量順'
'按用量排序': '使用量順',
'简易模式': 'シンプルモード',
'详细模式': '詳細モード'
},
'ru': {
'Bandix 流量监控': 'Монитор Трафика Bandix',
@@ -500,6 +515,7 @@ const translations = {
'界面语言': 'Язык интерфейса',
'选择 Bandix 流量监控的显示语言': 'Выберите язык отображения для Монитора Трафика Bandix',
'设备信息': 'Информация об устройстве',
'设备列表': 'Список устройств',
'LAN 流量': 'Трафик LAN',
'WAN 流量': 'Трафик WAN',
'限速设置': 'Ограничение скорости',
@@ -573,7 +589,9 @@ const translations = {
'升序': 'По возрастанию',
'降序': 'По убыванию',
'按速度排序': 'По скорости',
'按用量排序': 'По объёму'
'按用量排序': 'По объёму',
'简易模式': 'Простой режим',
'详细模式': 'Подробный режим'
}
};
@@ -781,7 +799,7 @@ return view.extend({
// 添加现代化样式,支持暗黑模式
var style = E('style', {}, `
.bandix-container {
padding: 24px;
padding: 8px;
background-color: ${darkMode ? '#1E1E1E' : '#f8fafc'};
min-height: 100vh;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
@@ -802,6 +820,48 @@ return view.extend({
margin: 0;
}
.bandix-header-right {
display: flex;
align-items: center;
gap: 12px;
}
.device-mode-group {
display: inline-flex;
border-radius: 4px;
overflow: hidden;
border: 1px solid ${darkMode ? '#252526' : '#d1d5db'};
}
.device-mode-btn {
background-color: ${darkMode ? '#333333' : '#ffffff'};
border: none;
border-right: 1px solid ${darkMode ? '#252526' : '#d1d5db'};
padding: 0 8px;
font-size: 0.75rem;
line-height: 1.4;
color: ${darkMode ? '#94a3b8' : '#6b7280'};
cursor: pointer;
user-select: none;
transition: all 0.15s ease;
white-space: nowrap;
height: 20px;
}
.device-mode-btn:last-child {
border-right: none;
}
.device-mode-btn:hover:not(.active) {
background-color: ${darkMode ? '#3a3a3a' : '#f9fafb'};
color: ${darkMode ? '#e2e8f0' : '#374151'};
}
.device-mode-btn.active {
background-color: #3b82f6;
color: white;
}
.bandix-badge {
background-color: ${darkMode ? '#333333' : '#f3f4f6'};
border: 1px solid ${darkMode ? '#252526' : '#d1d5db'};
@@ -833,7 +893,7 @@ return view.extend({
border-radius: 12px;
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, ${darkMode ? '0.3' : '0.1'});
overflow: hidden;
margin-bottom: 24px;
margin-bottom: 8px;
border: 1px solid ${darkMode ? '#252526' : '#3333331c'};
}
@@ -861,7 +921,7 @@ return view.extend({
.bandix-table th {
background-color: ${darkMode ? '#333333' : '#f9fafb'};
padding: 16px 20px;
padding: 6px 12px;
text-align: left;
font-weight: 600;
color: ${darkMode ? '#e2e8f0' : '#374151'};
@@ -940,7 +1000,7 @@ return view.extend({
}
.bandix-table td {
padding: 16px 20px;
padding: 6px 12px;
border: none;
vertical-align: middle;
word-wrap: break-word;
@@ -981,7 +1041,7 @@ return view.extend({
.device-info {
display: flex;
flex-direction: column;
gap: 4px;
gap: 2px;
}
.device-name {
@@ -1026,7 +1086,7 @@ return view.extend({
.traffic-info {
display: flex;
flex-direction: column;
gap: 8px;
gap: 4px;
}
.traffic-row {
@@ -1107,7 +1167,7 @@ return view.extend({
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 20px;
margin-bottom: 24px;
margin-bottom: 8px;
}
.stats-card {
@@ -1506,6 +1566,21 @@ return view.extend({
// 主要内容卡片
E('div', { 'class': 'bandix-card' }, [
E('div', { 'class': 'bandix-card-header history-header' }, [
E('div', { 'class': 'bandix-card-title' }, [
getTranslation('设备列表', language)
]),
E('div', { 'class': 'device-mode-group' }, [
E('button', {
'class': 'device-mode-btn' + (localStorage.getItem('bandix_device_mode') !== 'detailed' ? ' active' : ''),
'data-mode': 'simple'
}, getTranslation('简易模式', language)),
E('button', {
'class': 'device-mode-btn' + (localStorage.getItem('bandix_device_mode') === 'detailed' ? ' active' : ''),
'data-mode': 'detailed'
}, getTranslation('详细模式', language))
])
]),
E('div', { 'id': 'traffic-status' }, [
E('table', { 'class': 'bandix-table' }, [
E('thead', {}, [
@@ -1523,6 +1598,32 @@ return view.extend({
])
]);
// 设备信息模式切换
var deviceModeButtons = view.querySelectorAll('.device-mode-btn');
deviceModeButtons.forEach(function(btn) {
btn.addEventListener('click', function() {
var newMode = this.getAttribute('data-mode');
// 如果已经是当前模式,不做任何操作
if (this.classList.contains('active')) {
return;
}
// 保存到 localStorage
localStorage.setItem('bandix_device_mode', newMode);
// 更新按钮状态
deviceModeButtons.forEach(function(b) {
b.classList.remove('active');
});
this.classList.add('active');
// 刷新设备列表以应用新的显示模式
updateDeviceData();
});
});
// 创建限速设置模态框
var modal = E('div', { 'class': 'modal-overlay', 'id': 'rate-limit-modal' }, [
E('div', { 'class': 'modal' }, [
@@ -3028,6 +3129,10 @@ function formatRetentionSeconds(seconds, language) {
showRateLimitModal(device);
});
// 获取当前显示模式
var deviceMode = localStorage.getItem('bandix_device_mode') || 'simple';
var isDetailedMode = deviceMode === 'detailed';
// 构建设备信息元素
var deviceInfoElements = [
E('div', { 'class': 'device-name' }, [
@@ -3039,6 +3144,8 @@ function formatRetentionSeconds(seconds, language) {
E('div', { 'class': 'device-ip' }, device.ip)
];
// 详细模式下显示更多信息
if (isDetailedMode) {
// 只有当有设备有 IPv6 时才添加 IPv6 行
if (hasAnyIPv6) {
var lanIPv6 = filterLanIPv6(device.ipv6_addresses);
@@ -3061,6 +3168,7 @@ function formatRetentionSeconds(seconds, language) {
E('span', { 'style': 'color: #9ca3af; font-size: 0.75rem;' }, formatLastOnlineTime(device.last_online_ts, language))
])
);
}
var row = E('tr', {}, [
// 设备信息

View File

@@ -6,7 +6,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-passwall
PKG_VERSION:=25.9.23
PKG_VERSION:=25.11.1
PKG_RELEASE:=1
PKG_PO_VERSION:=$(PKG_VERSION)

View File

@@ -3,7 +3,26 @@ local appname = "passwall"
local datatypes = api.datatypes
m = Map(appname, "Sing-Box/Xray " .. translate("Shunt Rule"))
m.redirect = api.url()
m.redirect = api.url("rule")
if not arg[1] or not m:get(arg[1]) then
luci.http.redirect(m.redirect)
end
-- Add inline CSS to map description
m.description = (m.description or "") .. "\n" .. [[
<style>
div[id^="cbid.passwall."] .cbi-value-field {
display: flex;
flex-wrap: wrap;
gap: 1em;
}
div[id^="cbid.passwall."] .cbi-checkbox {
display: inline-flex;
align-items: center;
}
</style>
]]
function clean_text(text)
local nbsp = string.char(0xC2, 0xA0) -- 不间断空格U+00A0
@@ -30,10 +49,14 @@ protocol = s:option(MultiValue, "protocol", translate("Protocol"))
protocol:value("http")
protocol:value("tls")
protocol:value("bittorrent")
protocol.widget = "checkbox"
protocol.default = nil
o = s:option(MultiValue, "inbound", translate("Inbound Tag"))
o:value("tproxy", translate("Transparent proxy"))
o:value("socks", "Socks")
o.widget = "checkbox"
o.default = nil
network = s:option(ListValue, "network", translate("Network"))
network:value("tcp,udp", "TCP UDP")

File diff suppressed because it is too large Load Diff

View File

@@ -74,14 +74,14 @@
101.237.40.0/24
101.240.0.0/14
101.245.0.0/22
101.245.12.0/22
101.245.128.0/22
101.245.136.0/22
101.245.128.0/20
101.245.144.0/22
101.245.152.0/21
101.245.16.0/21
101.245.160.0/20
101.245.32.0/19
101.245.64.0/18
101.245.8.0/23
101.245.8.0/21
101.246.172.0/22
101.246.176.0/20
101.247.0.0/18
@@ -184,7 +184,8 @@
103.116.120.0/23
103.116.123.0/24
103.116.138.0/23
103.116.76.0/22
103.116.76.0/23
103.116.78.0/24
103.116.92.0/22
103.117.16.0/22
103.117.220.0/22
@@ -226,7 +227,9 @@
103.134.136.0/22
103.135.100.0/24
103.135.160.0/22
103.135.192.0/21
103.135.192.0/23
103.135.195.0/24
103.135.196.0/22
103.135.236.0/24
103.137.60.0/24
103.138.156.0/23
@@ -271,10 +274,8 @@
103.151.179.0/24
103.151.216.0/23
103.151.228.0/23
103.151.5.0/24
103.152.170.0/23
103.152.186.0/23
103.152.190.0/23
103.152.224.0/24
103.152.28.0/23
103.152.56.0/23
@@ -286,12 +287,10 @@
103.154.30.0/23
103.154.41.0/24
103.155.110.0/23
103.155.120.0/23
103.155.76.0/23
103.156.174.0/23
103.156.186.0/23
103.156.68.0/23
103.157.138.0/23
103.158.0.0/23
103.159.124.0/23
103.16.124.0/22
@@ -318,7 +317,6 @@
103.177.28.0/23
103.179.78.0/23
103.180.108.0/23
103.181.164.0/23
103.181.234.0/24
103.183.122.0/23
103.183.124.0/23
@@ -352,7 +350,7 @@
103.197.0.0/22
103.197.228.0/22
103.198.124.0/22
103.198.180.0/22
103.198.180.0/23
103.198.216.0/21
103.198.224.0/20
103.198.244.0/22
@@ -377,7 +375,8 @@
103.202.96.0/20
103.203.140.0/22
103.203.216.0/22
103.203.56.0/22
103.203.56.0/23
103.203.59.0/24
103.203.96.0/22
103.204.72.0/22
103.205.188.0/22
@@ -393,7 +392,7 @@
103.21.140.0/22
103.21.176.0/22
103.210.160.0/22
103.210.171.0/24
103.210.170.0/23
103.211.220.0/22
103.211.44.0/22
103.212.1.0/24
@@ -404,9 +403,8 @@
103.212.48.0/23
103.213.132.0/22
103.213.160.0/19
103.213.48.0/23
103.213.50.0/24
103.213.62.0/23
103.213.48.0/21
103.213.60.0/22
103.213.64.0/19
103.213.96.0/22
103.214.48.0/22
@@ -474,7 +472,6 @@
103.232.144.0/22
103.232.166.0/23
103.233.128.0/22
103.233.136.0/23
103.233.138.0/24
103.233.162.0/23
103.233.4.0/22
@@ -503,7 +500,6 @@
103.237.28.0/23
103.237.8.0/22
103.238.0.0/21
103.238.130.0/24
103.238.132.0/22
103.238.144.0/22
103.238.16.0/22
@@ -517,7 +513,6 @@
103.238.98.0/24
103.239.152.0/22
103.239.184.0/23
103.239.187.0/24
103.239.192.0/22
103.239.204.0/22
103.239.224.0/22
@@ -536,12 +531,9 @@
103.242.130.0/24
103.242.168.0/23
103.242.172.0/22
103.242.200.0/24
103.242.202.0/24
103.242.212.0/22
103.243.136.0/22
103.243.252.0/22
103.244.164.0/22
103.244.232.0/22
103.244.59.0/24
103.244.64.0/22
@@ -568,7 +560,7 @@
103.250.32.0/22
103.251.124.0/22
103.251.160.0/22
103.251.204.0/23
103.251.204.0/24
103.251.207.0/24
103.251.240.0/22
103.251.32.0/22
@@ -638,7 +630,7 @@
103.38.232.0/22
103.38.252.0/23
103.38.40.0/22
103.38.76.0/24
103.38.76.0/22
103.38.84.0/22
103.38.92.0/23
103.39.200.0/21
@@ -672,7 +664,9 @@
103.44.240.0/20
103.44.56.0/22
103.44.80.0/22
103.45.128.0/19
103.45.160.0/22
103.45.168.0/24
103.45.172.0/22
103.45.176.0/20
103.45.248.0/22
@@ -692,7 +686,6 @@
103.49.196.0/24
103.49.198.0/23
103.5.192.0/22
103.50.38.0/24
103.51.62.0/23
103.52.100.0/22
103.52.104.0/23
@@ -709,7 +702,6 @@
103.56.104.0/22
103.56.152.0/22
103.56.184.0/22
103.56.32.0/22
103.56.60.0/22
103.56.76.0/22
103.57.12.0/22
@@ -719,8 +711,8 @@
103.59.124.0/22
103.59.148.0/22
103.59.164.0/22
103.59.168.0/23
103.6.220.0/22
103.6.228.0/24
103.60.164.0/22
103.60.228.0/23
103.60.236.0/22
@@ -753,6 +745,7 @@
103.72.113.0/24
103.72.120.0/22
103.72.172.0/24
103.72.224.0/24
103.73.116.0/22
103.73.136.0/21
103.73.144.0/22
@@ -774,7 +767,6 @@
103.78.126.0/23
103.78.228.0/22
103.78.60.0/22
103.79.120.0/22
103.79.200.0/22
103.79.228.0/24
103.79.24.0/22
@@ -1026,6 +1018,7 @@
111.222.0.0/16
111.223.12.0/22
111.224.0.0/14
111.228.0.0/18
111.229.0.0/16
111.230.0.0/15
111.235.156.0/22
@@ -1096,11 +1089,7 @@
113.45.128.0/17
113.45.64.0/19
113.45.96.0/22
113.46.0.0/17
113.46.128.0/18
113.46.192.0/19
113.46.224.0/20
113.46.240.0/21
113.46.0.0/16
113.47.0.0/18
113.47.104.0/22
113.47.110.0/24
@@ -1174,6 +1163,7 @@
114.135.0.0/16
114.138.0.0/15
114.141.128.0/18
114.142.136.0/23
114.196.0.0/15
114.212.0.0/14
114.216.0.0/13
@@ -1221,15 +1211,18 @@
115.175.0.0/18
115.175.104.0/22
115.175.108.0/23
115.175.120.0/21
115.175.110.0/24
115.175.112.0/20
115.175.128.0/18
115.175.192.0/19
115.175.224.0/20
115.175.252.0/22
115.175.64.0/19
115.175.96.0/21
115.182.0.0/15
115.190.0.0/17
115.190.128.0/18
115.190.192.0/20
115.190.0.0/16
115.191.0.0/18
115.191.64.0/20
115.192.0.0/11
115.224.0.0/12
115.24.0.0/14
@@ -1238,7 +1231,7 @@
115.32.0.0/19
115.32.32.0/21
115.32.56.0/21
115.32.64.0/20
115.32.64.0/19
115.44.0.0/14
115.48.0.0/12
115.84.0.0/18
@@ -1305,6 +1298,7 @@
116.205.0.0/16
116.207.0.0/16
116.208.0.0/14
116.213.45.0/24
116.214.128.0/22
116.214.132.0/23
116.214.134.0/24
@@ -1326,6 +1320,7 @@
116.66.36.0/24
116.66.48.0/23
116.66.53.0/24
116.66.54.0/23
116.66.98.0/24
116.68.136.0/21
116.68.176.0/21
@@ -1385,6 +1380,8 @@
117.72.16.0/23
117.72.160.0/19
117.72.192.0/19
117.72.24.0/21
117.72.240.0/21
117.72.248.0/22
117.72.255.0/24
117.72.32.0/19
@@ -1416,16 +1413,16 @@
118.126.32.0/19
118.126.64.0/18
118.132.0.0/14
118.143.198.0/23
118.143.215.0/24
118.144.0.0/16
118.145.0.0/19
118.145.112.0/21
118.145.128.0/19
118.145.160.0/21
118.145.176.0/20
118.145.192.0/18
118.145.32.0/20
118.145.64.0/19
118.145.96.0/20
118.178.0.0/16
118.180.0.0/14
118.184.0.0/22
@@ -1497,8 +1494,8 @@
118.194.240.0/21
118.194.32.0/19
118.195.0.0/16
118.196.0.0/18
118.196.64.0/19
118.196.0.0/17
118.196.128.0/19
118.199.0.0/16
118.202.0.0/15
118.212.0.0/15
@@ -1573,7 +1570,6 @@
119.18.226.0/24
119.18.234.0/24
119.18.236.0/23
119.18.239.0/24
119.2.128.0/17
119.23.0.0/16
119.233.128.0/17
@@ -1609,7 +1605,6 @@
119.37.192.0/21
119.37.2.0/24
119.38.0.0/21
119.38.128.0/18
119.38.192.0/19
119.39.0.0/16
119.4.0.0/14
@@ -1711,7 +1706,10 @@
120.136.20.0/22
120.192.0.0/10
120.24.0.0/14
120.31.0.0/16
120.31.128.0/20
120.31.144.0/24
120.31.66.0/23
120.31.68.0/22
120.32.0.0/12
120.48.0.0/16
120.49.0.0/17
@@ -1927,18 +1925,15 @@
123.4.0.0/14
123.49.192.0/23
123.49.194.0/24
123.49.196.0/24
123.49.229.0/24
123.49.232.0/24
123.49.240.0/22
123.49.244.0/24
123.49.246.0/23
123.49.240.0/21
123.52.0.0/14
123.56.0.0/15
123.58.0.0/19
123.58.160.0/20
123.58.179.0/24
123.58.180.0/22
123.58.180.0/24
123.58.182.0/23
123.58.184.0/24
123.58.186.0/23
123.58.188.0/22
@@ -2006,9 +2001,10 @@
124.196.56.0/23
124.196.58.0/24
124.196.66.0/24
124.196.72.0/24
124.196.77.0/24
124.196.80.0/22
124.196.84.0/24
124.196.84.0/23
124.200.0.0/16
124.202.0.0/16
124.203.176.0/20
@@ -2034,7 +2030,6 @@
124.64.0.0/15
124.66.0.0/17
124.67.0.0/16
124.68.252.0/23
124.70.0.0/16
124.71.0.0/17
124.71.128.0/18
@@ -2152,7 +2147,6 @@
140.75.0.0/16
143.14.49.0/24
143.20.147.0/24
143.20.66.0/24
143.64.0.0/16
144.0.0.0/16
144.12.0.0/16
@@ -2168,7 +2162,6 @@
144.7.0.0/17
145.14.71.0/24
145.14.72.0/22
145.14.79.0/24
145.14.81.0/24
145.14.82.0/24
145.14.84.0/24
@@ -2203,7 +2196,6 @@
150.242.80.0/22
150.242.96.0/22
150.255.0.0/16
151.241.174.0/24
152.104.128.0/17
152.136.0.0/16
153.0.0.0/16
@@ -2218,12 +2210,8 @@
154.208.144.0/20
154.208.160.0/21
154.208.172.0/23
154.213.4.0/23
154.218.6.0/23
154.223.168.0/24
154.223.179.0/24
154.223.180.0/24
154.38.104.0/22
154.48.237.0/24
154.72.42.0/24
154.72.44.0/24
@@ -2271,7 +2259,6 @@
16.2.142.0/23
160.19.208.0/22
160.19.76.0/23
160.19.82.0/24
160.191.0.0/24
160.20.18.0/23
160.202.152.0/22
@@ -2300,7 +2287,6 @@
163.177.0.0/16
163.179.0.0/16
163.204.0.0/16
163.223.173.0/24
163.223.178.0/23
163.228.0.0/16
163.244.246.0/24
@@ -2311,7 +2297,9 @@
163.53.60.0/22
163.53.88.0/21
163.61.202.0/23
163.61.214.0/24
163.61.214.0/23
165.101.122.0/23
165.101.70.0/23
166.111.0.0/16
167.139.0.0/16
167.148.46.0/24
@@ -2483,7 +2471,6 @@
192.144.128.0/17
192.163.11.0/24
192.232.97.0/24
192.55.46.0/24
193.112.0.0/16
193.119.10.0/23
193.119.12.0/23
@@ -2498,13 +2485,11 @@
193.119.4.0/24
193.119.6.0/24
193.119.8.0/24
194.119.13.0/24
194.119.15.0/24
193.233.49.0/24
194.127.229.0/24
194.138.202.0/23
194.138.245.0/24
194.15.39.0/24
195.114.203.0/24
198.208.112.0/23
198.208.17.0/24
198.208.19.0/24
@@ -2580,9 +2565,11 @@
202.179.240.0/20
202.181.120.0/21
202.181.28.0/24
202.189.16.0/21
202.189.16.0/20
202.189.3.0/24
202.189.32.0/20
202.189.4.0/22
202.189.48.0/22
202.189.8.0/21
202.192.0.0/12
202.38.128.0/23
@@ -2645,8 +2632,6 @@
202.91.224.0/20
202.91.240.0/21
202.91.248.0/22
202.91.36.0/24
202.91.38.0/24
202.93.252.0/22
202.95.0.0/19
202.96.0.0/13
@@ -2689,7 +2674,6 @@
203.12.204.0/23
203.12.91.0/24
203.12.93.0/24
203.12.95.0/24
203.129.10.0/23
203.129.12.0/22
203.129.8.0/24
@@ -2723,9 +2707,12 @@
203.166.188.0/23
203.166.191.0/24
203.168.0.0/22
203.168.129.0/24
203.168.16.0/23
203.168.18.0/24
203.168.8.0/24
203.168.5.0/24
203.168.6.0/23
203.168.8.0/21
203.170.58.0/23
203.174.4.0/24
203.174.7.0/24
@@ -2781,7 +2768,6 @@
203.215.236.0/24
203.223.21.0/24
203.25.208.0/20
203.25.48.0/24
203.25.52.0/24
203.3.112.0/21
203.3.80.0/21
@@ -2961,8 +2947,6 @@
203.99.20.0/22
203.99.24.0/21
204.13.175.0/24
207.226.153.0/24
207.226.154.0/24
210.12.0.0/16
210.13.0.0/17
210.13.192.0/19
@@ -3244,12 +3228,17 @@
218.240.128.0/19
218.240.160.0/21
218.240.168.0/24
218.240.176.0/21
218.240.184.0/24
218.240.176.0/20
218.241.112.0/22
218.241.116.0/23
218.241.118.0/24
218.241.121.0/24
218.241.122.0/23
218.241.124.0/22
218.241.128.0/17
218.241.16.0/21
218.241.24.0/22
218.241.96.0/19
218.241.96.0/20
218.242.0.0/16
218.244.0.0/19
218.244.128.0/18
@@ -3322,7 +3311,8 @@
219.234.80.0/20
219.234.96.0/19
219.235.0.0/20
219.235.128.0/19
219.235.128.0/20
219.235.144.0/21
219.235.192.0/23
219.235.207.0/24
219.235.224.0/22
@@ -3362,6 +3352,7 @@
220.152.128.0/17
220.154.0.0/20
220.154.128.0/22
220.154.132.0/23
220.154.140.0/24
220.154.144.0/24
220.154.16.0/22
@@ -3481,7 +3472,6 @@
222.59.252.0/22
222.64.0.0/11
223.0.1.0/24
223.0.10.0/24
223.0.12.0/23
223.0.126.0/24
223.0.15.0/24
@@ -3489,7 +3479,7 @@
223.0.2.0/24
223.0.30.0/24
223.0.40.0/23
223.0.8.0/23
223.0.8.0/22
223.128.0.0/15
223.144.0.0/12
223.160.0.0/20
@@ -3549,6 +3539,7 @@
223.4.0.0/14
223.64.0.0/10
223.8.0.0/13
23.133.188.0/24
23.161.8.0/24
23.236.111.0/24
27.0.128.0/24
@@ -3574,6 +3565,7 @@
27.50.128.0/17
27.8.0.0/13
27.98.224.0/19
27.99.128.0/17
31.56.66.0/24
31.57.10.0/24
31.57.248.0/24
@@ -3626,6 +3618,7 @@
40.126.64.0/18
40.162.0.0/16
40.72.0.0/15
42.0.128.0/17
42.100.0.0/14
42.120.0.0/15
42.122.0.0/16
@@ -3696,7 +3689,6 @@
43.195.0.0/20
43.196.0.0/16
43.224.12.0/22
43.224.23.0/24
43.224.24.0/22
43.224.240.0/24
43.224.52.0/23
@@ -3714,8 +3706,13 @@
43.226.128.0/19
43.226.164.0/22
43.226.236.0/22
43.226.32.0/19
43.226.64.0/20
43.226.32.0/20
43.226.48.0/24
43.226.50.0/23
43.226.52.0/22
43.226.56.0/21
43.226.64.0/21
43.226.76.0/22
43.227.104.0/22
43.227.140.0/22
43.227.152.0/21
@@ -3724,7 +3721,10 @@
43.227.192.0/19
43.227.252.0/22
43.227.56.0/21
43.227.64.0/21
43.227.64.0/22
43.227.69.0/24
43.227.70.0/23
43.227.80.0/20
43.228.0.0/19
43.228.116.0/22
43.228.204.0/22
@@ -3761,7 +3761,7 @@
43.240.200.0/23
43.240.202.0/24
43.240.204.0/22
43.240.220.0/22
43.240.216.0/21
43.240.56.0/21
43.240.72.0/22
43.241.16.0/22
@@ -3863,11 +3863,11 @@
44.30.28.0/24
44.31.216.0/24
44.31.28.0/24
44.31.42.0/24
44.31.81.0/24
44.31.96.0/24
44.32.143.0/24
44.32.188.0/24
44.32.191.0/24
44.32.192.0/24
45.112.232.0/22
45.113.20.0/22
@@ -3913,6 +3913,7 @@
45.127.129.0/24
45.127.131.0/24
45.127.144.0/21
45.135.149.0/24
45.147.6.0/24
45.151.47.0/24
45.157.88.0/24
@@ -3938,6 +3939,7 @@
45.250.28.0/22
45.250.32.0/21
45.250.40.0/22
45.251.0.0/23
45.251.120.0/22
45.251.20.0/22
45.251.8.0/22
@@ -3965,9 +3967,7 @@
45.254.8.0/23
45.255.152.0/22
45.40.192.0/18
45.59.106.0/24
45.65.20.0/22
45.87.101.0/24
45.9.11.0/24
47.112.0.0/13
47.120.0.0/14
@@ -3975,11 +3975,11 @@
47.96.0.0/12
49.112.0.0/13
49.120.0.0/14
49.128.203.0/24
49.128.220.0/24
49.128.223.0/24
49.140.0.0/15
49.208.0.0/14
49.213.62.0/24
49.221.128.0/19
49.221.26.0/23
49.221.64.0/19
@@ -4051,7 +4051,6 @@
58.240.0.0/12
58.30.0.0/15
58.32.0.0/11
58.66.192.0/18
58.67.128.0/17
58.68.236.0/24
58.68.247.0/24
@@ -4114,7 +4113,6 @@
59.152.36.0/24
59.152.38.0/23
59.153.116.0/22
59.153.136.0/22
59.153.164.0/22
59.153.168.0/24
59.153.32.0/22
@@ -4218,8 +4216,7 @@
8.148.0.0/19
8.148.128.0/17
8.148.36.0/22
8.148.40.0/23
8.148.43.0/24
8.148.40.0/22
8.148.64.0/18
8.149.0.0/16
8.150.0.0/20
@@ -4229,13 +4226,12 @@
8.160.0.0/15
8.162.0.0/18
8.163.0.0/16
8.164.0.0/16
8.164.0.0/14
81.173.18.0/23
81.173.20.0/22
81.173.28.0/24
81.68.0.0/14
82.156.0.0/15
84.247.114.0/24
84.54.2.0/23
85.237.205.0/24
94.191.0.0/17

View File

@@ -17,9 +17,9 @@
2001:dd8:1::/48
2001:dd9::/48
2001:df0:ac40::/48
2001:df1:61c0::/48
2001:df3:3a80::/48
2001:df3:8b80::/48
2001:df5:4740::/48
2001:df7:1480::/48
2400:1160::/32
2400:3200::/32
@@ -78,7 +78,7 @@
2400:9380:9009::/48
2400:9380:900a::/48
2400:9380:9020::/47
2400:9380:9040::/47
2400:9380:9040::/48
2400:9380:9050::/47
2400:9380:9060::/48
2400:9380:9071::/48
@@ -104,6 +104,7 @@
2400:a860:1::/48
2400:a860:2::/47
2400:a860:4::/47
2400:a860:6::/48
2400:a980::/29
2400:ae00:1981::/48
2400:b200::/32
@@ -115,7 +116,6 @@
2400:cb80:e40::/44
2400:da00::/32
2400:dd00::/28
2400:ebc0::/32
2400:ee00::/32
2400:f6e0::/32
2400:f720::/32
@@ -131,7 +131,6 @@
2401:20::/40
2401:2780::/32
2401:2e00::/32
2401:33c0::/32
2401:3480:2000::/48
2401:3480:3000::/36
2401:3480::/36
@@ -201,23 +200,38 @@
2401:de00::/32
2401:ec00::/32
2401:f860:100::/40
2401:f860:7::/48
2401:f860:86::/47
2401:f860:88::/47
2401:f860:90::/46
2401:f860:94::/47
2401:f860:90::/45
2401:f860:a::/47
2401:f860:c::/46
2401:f860:f100::/40
2401:f860:f6::/48
2401:f860:f9::/48
2401:fa00:40::/43
2402:1440::/32
2402:1460::/32
2402:2000::/32
2402:20e0:f000::/48
2402:3180:8000::/33
2402:3180::/46
2402:3c00::/32
2402:3f80:1400::/40
2402:4440::/32
2402:4440:9000::/39
2402:4440:9200::/48
2402:4440:9400::/48
2402:4440:9600::/48
2402:4440:9800::/48
2402:4440:9810::/48
2402:4440:9900::/48
2402:4440:9a00::/48
2402:4440:9b00::/48
2402:4440:9c00::/48
2402:4440:9d00::/48
2402:4440:9e00::/48
2402:4440:a000::/39
2402:4440:a800::/46
2402:4440:a810::/46
2402:4b80::/32
2402:4e00::/32
2402:5e40::/32
@@ -228,9 +242,7 @@
2402:6fc0::/48
2402:7040::/32
2402:7d80:240::/47
2402:7d80:6666::/48
2402:7d80:8888::/48
2402:7d80:9999::/48
2402:7d80::/48
2402:840:d000::/46
2402:840:e000::/46
@@ -296,6 +308,7 @@
2403:a140:10::/48
2403:a200::/32
2403:ac00::/32
2403:ad80:101c::/48
2403:ad80:8008::/48
2403:b400::/32
2403:c80::/32
@@ -393,7 +406,6 @@
2406:52c0::/32
2406:5340:6666::/48
2406:5340:8888::/48
2406:5ac0::/32
2406:6100::/32
2406:840:8100::/40
2406:840:9000::/44
@@ -402,8 +414,7 @@
2406:840:9961::/48
2406:840:9962::/47
2406:840:996c::/48
2406:840:a7fe::/48
2406:840:a800::/37
2406:840:c200::/40
2406:840:e080::/44
2406:840:e0cf::/48
2406:840:e0e0::/46
@@ -415,11 +426,12 @@
2406:840:e230::/44
2406:840:e260::/48
2406:840:e2cf::/48
2406:840:e600::/45
2406:840:e608::/46
2406:840:e621::/48
2406:840:e600::/46
2406:840:e604::/47
2406:840:e606::/48
2406:840:e60d::/48
2406:840:e620::/47
2406:840:e666::/47
2406:840:e720::/44
2406:840:e770::/48
2406:840:e777::/48
2406:840:e80f::/48
@@ -447,15 +459,16 @@
2406:840:fc80::/42
2406:840:fcc0::/44
2406:840:fcd0::/48
2406:840:fcf0::/46
2406:840:fcf4::/47
2406:840:fd40::/42
2406:840:fd80::/44
2406:840:fd9f::/48
2406:840:fda0::/43
2406:840:fdc0::/44
2406:840:fdd1::/48
2406:840:fde5::/48
2406:840:fde6::/47
2406:840:fe27::/48
2406:840:fe60::/44
2406:840:fe90::/46
2406:840:fe94::/48
2406:840:fe96::/47
@@ -473,11 +486,12 @@
2406:840:fecc::/47
2406:840:fecf::/48
2406:840:fed1::/48
2406:840:fed6::/48
2406:840:fed8::/48
2406:840:fedb::/48
2406:840:fedc::/47
2406:840:fedc::/48
2406:840:fedf::/48
2406:840:fef0::/48
2406:840:fef0::/47
2406:840:fef3::/48
2406:840:fef4::/48
2406:840:fef6::/47
@@ -720,7 +734,6 @@
2408:8406:cc0::/42
2408:8406:d00::/41
2408:8406:d80::/42
2408:8407:500::/43
2408:8409:100::/41
2408:8409:1800::/40
2408:8409:180::/42
@@ -916,7 +929,7 @@
2408:842a::/31
2408:842c::/32
2408:842e::/32
2408:8431::/32
2408:8430::/31
2408:8434::/30
2408:8438::/31
2408:843c::/30
@@ -1173,8 +1186,10 @@
240a:420a::/31
240a:4224:9000::/44
240a:4224:a000::/44
240a:4224:c000::/44
240a:4224:d000::/44
240a:4224:e000::/44
240a:4225:1000::/44
240a:4230::/31
240a:4242::/31
240a:4280::/26
@@ -1199,14 +1214,15 @@
240e::/20
2602:2e0:ff::/48
2602:f7ee:ee::/48
2602:f92a:a471::/48
2602:f92a:a473::/48
2602:f92a:a478::/48
2602:f92a:d1ff::/48
2602:f92a:dead::/48
2602:f92a:e100::/44
2602:f93b:400::/38
2602:f9ba:10c::/48
2602:f9ba:a8::/48
2602:feda:182::/47
2602:fab0:11::/48
2602:feda:1bf::/48
2602:feda:1d1::/48
2602:feda:1df::/48
@@ -1230,8 +1246,6 @@
2804:1e48:9002::/48
2a01:f100:100::/48
2a01:f100:1f8::/48
2a01:ffc7:100::/40
2a03:5840:126::/48
2a04:3e00:1002::/48
2a04:f580:8010::/47
2a04:f580:8090::/48
@@ -1246,7 +1260,6 @@
2a04:f580:9060::/48
2a04:f580:9070::/48
2a04:f580:9080::/48
2a04:f580:9090::/48
2a04:f580:9210::/48
2a04:f580:9212::/47
2a04:f580:9220::/48
@@ -1264,18 +1277,15 @@
2a06:3603::/32
2a06:3604::/30
2a06:9f81:4600::/43
2a06:9f81:4640::/44
2a06:9f81:4660::/44
2a06:9f81:4620::/44
2a06:9f81:4640::/43
2a06:a005:1c40::/44
2a06:a005:260::/43
2a06:a005:280::/43
2a06:a005:2a0::/44
2a06:a005:8d0::/44
2a06:a005:9e0::/44
2a06:a005:a13::/48
2a06:a005:e9a::/48
2a09:54c6:3000::/36
2a09:54c6:6000::/35
2a09:54c6:b000::/36
2a09:54c6:c000::/36
2a09:54c6:e000::/36
@@ -1292,9 +1302,10 @@
2a0b:2542::/48
2a0b:4b81:1001::/48
2a0b:4e07:b8::/47
2a0c:9a40:84e0::/48
2a0c:9a40:8fc1::/48
2a0c:9a40:8fc2::/47
2a0c:9a40:8fc4::/48
2a0c:b641:571::/48
2a0c:b641:d40::/44
2a0e:97c0:5ef::/48
2a0e:97c0:83f::/48
2a0e:9b00::/29
@@ -1302,7 +1313,7 @@
2a0e:aa06:440::/48
2a0e:aa06:490::/44
2a0e:aa06:4e0::/44
2a0e:aa06:500::/44
2a0e:aa06:501::/48
2a0e:aa06:520::/48
2a0e:aa06:525::/48
2a0e:aa06:541::/48
@@ -1317,14 +1328,12 @@
2a0e:aa07:e0e0::/44
2a0e:aa07:e151::/48
2a0e:aa07:e155::/48
2a0e:aa07:e15f::/48
2a0e:aa07:e160::/47
2a0e:aa07:e162::/48
2a0e:aa07:e16a::/48
2a0e:aa07:e1a0::/44
2a0e:aa07:e1e1::/48
2a0e:aa07:e1e2::/47
2a0e:aa07:e1e4::/47
2a0e:aa07:e1e6::/48
2a0e:aa07:e1e0::/44
2a0e:aa07:e200::/44
2a0e:aa07:e210::/48
2a0e:aa07:e21c::/47
@@ -1342,7 +1351,15 @@
2a0e:b107:c10::/48
2a0e:b107:da0::/44
2a0e:b107:dce::/48
2a0f:1cc5:f00::/47
2a0f:1cc5:f02::/48
2a0f:1cc5:f05::/48
2a0f:5707:ac00::/47
2a0f:6284:4b00::/40
2a0f:6284:4c30::/48
2a0f:6284:4c40::/43
2a0f:6284:4c60::/44
2a0f:6284:4c80::/43
2a0f:7803:e300::/40
2a0f:7803:f5d0::/44
2a0f:7803:f5e0::/43
@@ -1356,39 +1373,33 @@
2a0f:7803:fa24::/46
2a0f:7803:faf3::/48
2a0f:7803:fe41::/48
2a0f:7803:fe44::/46
2a0f:7803:fe4e::/48
2a0f:7803:fe45::/48
2a0f:7803:fe81::/48
2a0f:7803:fe82::/48
2a0f:7804:f650::/44
2a0f:7804:f9f0::/44
2a0f:7807::/32
2a0f:7d07::/32
2a0f:85c1:ba5::/48
2a0f:85c1:bfe::/48
2a0f:85c1:ca0::/44
2a0f:85c1:ce1::/48
2a0f:85c1:cf1::/48
2a0f:85c1:d90::/48
2a0f:9400:6110::/48
2a0f:9400:7700::/48
2a0f:ac00::/29
2a0f:ea47:fc1d::/48
2a10:2f00:15a::/48
2a10:67c2:2::/48
2a10:ccc0:d00::/46
2a10:ccc0:d0a::/47
2a10:ccc0:d0c::/47
2a10:ccc6:66c4::/48
2a10:ccc6:66c6::/48
2a10:ccc6:66c8::/47
2a10:ccc6:66ca::/48
2a10:ccc6:66cc::/47
2a10:ccc6:66c8::/48
2a10:ccc6:66cc::/46
2a12:f8c3::/36
2a13:1800:10::/48
2a13:1800:300::/44
2a13:1800:80::/44
2a13:1800::/48
2a13:1801:180::/43
2a13:a5c3:ff10::/44
2a13:a5c3:ff21::/48
2a13:a5c3:ff50::/44
2a13:a5c7:1800::/40
@@ -1397,10 +1408,8 @@
2a13:a5c7:2121::/48
2a13:a5c7:2301::/48
2a13:a5c7:2302::/48
2a13:a5c7:23c0::/42
2a13:a5c7:2600::/40
2a13:a5c7:23c0::/48
2a13:a5c7:2801::/48
2a13:a5c7:2803::/48
2a13:a5c7:3108::/48
2a13:a5c7:31a0::/43
2a13:a5c7:3301::/48
@@ -1411,7 +1420,7 @@
2a14:67c1:20::/44
2a14:67c1:702::/47
2a14:67c1:704::/48
2a14:67c1:70::/47
2a14:67c1:70::/48
2a14:67c1:73::/48
2a14:67c1:74::/48
2a14:67c1:a010::/44
@@ -1421,14 +1430,10 @@
2a14:67c1:a02a::/48
2a14:67c1:a02f::/48
2a14:67c1:a040::/47
2a14:67c1:a061::/48
2a14:67c1:a064::/48
2a14:67c1:a090::/45
2a14:67c1:a099::/48
2a14:67c1:a100::/43
2a14:67c1:a125::/48
2a14:67c1:a144::/48
2a14:67c1:a150::/44
2a14:67c1:b000::/48
2a14:67c1:b065::/48
2a14:67c1:b066::/48
@@ -1438,80 +1443,72 @@
2a14:67c1:b107::/48
2a14:67c1:b130::/46
2a14:67c1:b134::/47
2a14:67c1:b136::/48
2a14:67c1:b140::/48
2a14:67c1:b4a1::/48
2a14:67c1:b4a2::/48
2a14:67c1:b4a8::/47
2a14:67c1:b4aa::/48
2a14:67c1:b4c0::/45
2a14:67c1:b4d0::/44
2a14:67c1:b4e0::/43
2a14:67c1:b500::/47
2a14:67c1:b549::/48
2a14:67c1:b561::/48
2a14:67c1:b563::/48
2a14:67c1:b566::/48
2a14:67c1:b581::/48
2a14:67c1:b578::/48
2a14:67c1:b582::/48
2a14:67c1:b586::/48
2a14:67c1:b588::/47
2a14:67c1:b590::/47
2a14:67c1:b590::/48
2a14:67c1:b599::/48
2a14:67c5:1900::/40
2a14:67c1:b5a1::/48
2a14:67c1:c300::/40
2a14:7580:740::/44
2a14:7580:750::/47
2a14:7580:9200::/40
2a14:7580:9208::/48
2a14:7580:9220::/44
2a14:7580:9400::/39
2a14:7580:9600::/46
2a14:7580:960c::/48
2a14:7580:d000::/37
2a14:7580:d800::/39
2a14:7580:da00::/40
2a14:7580:e200::/40
2a14:7580:fa01::/48
2a14:7580:fe00::/40
2a14:7580:fff4::/48
2a14:7580:fff7::/48
2a14:7580:fffa::/48
2a14:7581:30b5::/48
2a14:7581:3100::/40
2a14:7581:3400::/47
2a14:7581:9010::/44
2a14:7581:b10::/48
2a14:7581:b12::/48
2a14:7581:b15::/48
2a14:7581:3401::/48
2a14:7581:b12::/47
2a14:7581:b14::/47
2a14:7581:b20::/46
2a14:7581:b32::/47
2a14:7581:b40::/48
2a14:7581:b44::/48
2a14:7581:b46::/47
2a14:7581:b48::/48
2a14:7581:b4a::/48
2a14:7581:b60::/48
2a14:7581:b62::/47
2a14:7581:b64::/46
2a14:7581:b6c::/47
2a14:7581:b6e::/48
2a14:7581:b82::/47
2a14:7581:ba0::/48
2a14:7581:ba2::/47
2a14:7581:ba4::/48
2a14:7581:bbb::/48
2a14:7581:bc2::/48
2a14:7581:bcd::/48
2a14:7581:bff::/48
2a14:7581:ffb::/48
2a14:7581:ffd::/48
2a14:7583:f201::/48
2a14:7583:f203::/48
2a14:7583:f300::/46
2a14:7583:f304::/48
2a14:7583:f304::/47
2a14:7583:f460::/44
2a14:7583:f4f1::/48
2a14:7583:f4fe::/48
2a14:7583:f500::/48
2a14:7583:f701::/48
2a14:7583:f702::/47
2a14:7583:f704::/47
2a14:7583:f707::/48
2a14:7583:f708::/48
2a14:7583:f704::/46
2a14:7583:f708::/47
2a14:7583:f70a::/48
2a14:7583:f743::/48
2a14:7583:f764::/48
2a14:7584::/36
2a14:7c0:4a01::/48
2a14:7c0:5103::/48
2c0f:f7a8:8011::/48
2c0f:f7a8:8050::/48
2c0f:f7a8:805f::/48

View File

@@ -117,6 +117,7 @@
91vps.club
92ccav.com
991.com
996.icu
99btgc01.com
99cn.info
9bis.com
@@ -303,6 +304,7 @@ apetube.com
api-secure.recaptcha.net
api-verify.recaptcha.net
api.ai
api.palworldgame.com
api.pureapk.com
api.recaptcha.net
api.steampowered.com
@@ -360,6 +362,7 @@ asia-gaming.com
asiaharvest.org
asianage.com
asianews.it
asianfanfics.com
asiansexdiary.com
asiaone.com
asiatgp.com
@@ -748,7 +751,6 @@ btc98.com
btcbank.bank
btctrade.im
btdig.com
btdigg.org
btguard.com
btku.me
btku.org
@@ -1166,6 +1168,7 @@ csuchen.de
csw.org.uk
ct.org.tw
ctao.org
ctinets.com
ctinews.com
ctitv.com.tw
ctowc.org
@@ -1341,6 +1344,7 @@ dnvod.tv
doc.new
docker.com
docker.io
dockerstatus.com
docs.deno.com
docs.new
doctorvoice.org
@@ -1797,6 +1801,8 @@ freedominfonetweb.wordpress.com
freedomsherald.org
freeforums.org
freegao.com
freegpt.es
freegpt.tech
freehongkong.org
freeilhamtohti.org
freekazakhs.org
@@ -2691,6 +2697,7 @@ internet.org
internetdefenseleague.org
internetfreedom.org
internetpopculture.com
interseclab.org
inthenameofconfuciusmovie.com
investigating.wordpress.com
invidio.us
@@ -3656,6 +3663,7 @@ occupytiananmen.com
ocreampies.com
ocry.com
october-review.org
octocaptcha.com
oculus.com
oculuscdn.com
odysee.com
@@ -4463,6 +4471,7 @@ solana.com
solarsystem.nasa.gov
solidaritetibet.org
solidfiles.com
solscan.io
solv.finance
somee.com
songjianjun.com
@@ -4683,8 +4692,10 @@ tanc.org
tangren.us
tanks.gg
taoism.net
tap.io
tapanwap.com
tapatalk.com
taptap.io
tardigrade.io
tarr.uspto.gov
taup.net
@@ -4994,6 +5005,7 @@ trt.net.tr
trtc.com.tw
truebuddha-md.org
trulyergonomic.com
trustwallet.com
truthsocial.com
truveo.com
tryheart.jp
@@ -5301,6 +5313,7 @@ vijayatemple.org
vilanet.me
vilavpn.com
vimeo.com
vimeocdn.com
vimperator.org
vincnd.com
vine.co
@@ -5449,6 +5462,7 @@ webpkgcache.com
webrtc.org
webrush.net
webs-tv.net
websdr.org
website.informer.com
website.new
websitepulse.com
@@ -5519,6 +5533,7 @@ wikilivres.info
wikimapia.org
wikimedia.org
wikinews.org
wikipedia.com
wikipedia.org
wikisource.org
wikiversity.org
@@ -5693,6 +5708,7 @@ xn--ngstr-lra8j.com
xn--noss43i.com
xn--oiq.cc
xn--p8j9a0d9c9a.xn--q9jyb4c
xn--u2u927b.com
xnpool.com
xnxx.com
xpdo.net
@@ -5818,6 +5834,7 @@ z-lib.gd
z-lib.gl
z-lib.io
z-lib.org
z-library.ec
z-library.sk
zacebook.com
zalmos.com

View File

@@ -7,6 +7,8 @@ PKG_VERSION:=190
PKG_RELEASE:=3
PKG_CONFIG_DEPENDS:= \
CONFIG_PACKAGE_$(PKG_NAME)_Iptables_Transparent_Proxy \
CONFIG_PACKAGE_$(PKG_NAME)_Nftables_Transparent_Proxy \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_NONE_V2RAY \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_V2ray \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Xray \
@@ -39,9 +41,9 @@ PKG_CONFIG_DEPENDS:= \
LUCI_TITLE:=SS/SSR/V2Ray/Trojan/NaiveProxy/Tuic/ShadowTLS/Hysteria/Socks5/Tun LuCI interface
LUCI_PKGARCH:=all
LUCI_DEPENDS:= \
+coreutils +coreutils-base64 +dns2tcp +dnsmasq-full +@PACKAGE_dnsmasq_full_ipset +ipset +kmod-ipt-nat +jq \
+ip-full +iptables +iptables-mod-tproxy +lua +lua-neturl +libuci-lua +microsocks \
+tcping +resolveip +shadowsocksr-libev-ssr-check +curl +nping \
+coreutils +coreutils-base64 +dns2tcp +dnsmasq-full \
+jq +ip-full +lua +lua-neturl +libuci-lua +microsocks \
+tcping +resolveip +curl +nping \
+PACKAGE_$(PKG_NAME)_INCLUDE_V2ray:curl \
+PACKAGE_$(PKG_NAME)_INCLUDE_V2ray:v2ray-core \
+PACKAGE_$(PKG_NAME)_INCLUDE_Xray:curl \
@@ -68,14 +70,40 @@ LUCI_DEPENDS:= \
+PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Xray_Plugin:xray-plugin \
+PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Libev_Client:shadowsocksr-libev-ssr-local \
+PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Libev_Client:shadowsocksr-libev-ssr-redir \
+PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Libev_Server:shadowsocksr-libev-ssr-server \
+PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Libev_Client:shadowsocksr-libev-ssr-redir \
+PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Libev_Server:shadowsocksr-libev-ssr-check \
+PACKAGE_$(PKG_NAME)_INCLUDE_Trojan:trojan
define Package/$(PKG_NAME)/config
select PACKAGE_luci-lib-ipkg if PACKAGE_$(PKG_NAME)
select PACKAGE_luci-lua-runtime if PACKAGE_$(PKG_NAME)
choice
prompt "Transparent Proxy Backend"
default PACKAGE_$(PKG_NAME)_Iptables_Transparent_Proxy if ! PACKAGE_firewall4
default PACKAGE_$(PKG_NAME)_Nftables_Transparent_Proxy if PACKAGE_firewall4
config PACKAGE_$(PKG_NAME)_Iptables_Transparent_Proxy
bool "Iptables Transparent Proxy"
select PACKAGE_dnsmasq_full_ipset
select PACKAGE_ipset
select PACKAGE_iptables
select PACKAGE_iptables-zz-legacy
select PACKAGE_iptables-mod-conntrack-extra
select PACKAGE_iptables-mod-iprange
select PACKAGE_iptables-mod-socket
select PACKAGE_iptables-mod-tproxy
select PACKAGE_kmod-ipt-nat
config PACKAGE_$(PKG_NAME)_Nftables_Transparent_Proxy
bool "Nftables Transparent Proxy"
select PACKAGE_dnsmasq_full_nftset
select PACKAGE_nftables
select PACKAGE_kmod-nft-socket
select PACKAGE_kmod-nft-tproxy
select PACKAGE_kmod-nft-nat
endchoice
choice
prompt "Shadowsocks Client Selection"
default PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Rust_Client if aarch64||arm||i386||mips||mipsel||x86_64

View File

@@ -30,6 +30,7 @@ function index()
entry({"admin", "services", "shadowsocksr", "delete"}, call("act_delete"))
--[[Backup]]
entry({"admin", "services", "shadowsocksr", "backup"}, call("create_backup")).leaf = true
end
function subscribe()
@@ -48,36 +49,70 @@ end
function act_ping()
local e = {}
local domain = luci.http.formvalue("domain")
local port = luci.http.formvalue("port")
local port = tonumber(luci.http.formvalue("port") or 0)
local transport = luci.http.formvalue("transport")
local wsPath = luci.http.formvalue("wsPath")
local wsPath = luci.http.formvalue("wsPath") or ""
local tls = luci.http.formvalue("tls")
e.index = luci.http.formvalue("index")
local iret = luci.sys.call("ipset add ss_spec_wan_ac " .. domain .. " 2>/dev/null")
local use_nft = luci.sys.call("command -v nft >/dev/null") == 0
local iret = false
if use_nft then
iret = luci.sys.call("nft add element inet ss_spec ss_spec_wan_ac { " .. domain .. " } 2>/dev/null") == 0
else
iret = luci.sys.call("ipset add ss_spec_wan_ac " .. domain .. " 2>/dev/null") == 0
end
if transport == "ws" then
local prefix = tls == '1' and "https://" or "http://"
local address = prefix .. domain .. ':' .. port .. wsPath
local result = luci.sys.exec("curl --http1.1 -m 2 -ksN -o /dev/null -w 'time_connect=%{time_connect}\nhttp_code=%{http_code}' -H 'Connection: Upgrade' -H 'Upgrade: websocket' -H 'Sec-WebSocket-Key: SGVsbG8sIHdvcmxkIQ==' -H 'Sec-WebSocket-Version: 13' "..address)
local result = luci.sys.exec(
"curl --http1.1 -m 2 -ksN -o /dev/null " ..
"-w 'time_connect=%{time_connect}\nhttp_code=%{http_code}' " ..
"-H 'Connection: Upgrade' -H 'Upgrade: websocket' " ..
"-H 'Sec-WebSocket-Key: SGVsbG8sIHdvcmxkIQ==' " ..
"-H 'Sec-WebSocket-Version: 13' " .. address
)
e.socket = string.match(result,"http_code=(%d+)") == "101"
e.ping = tonumber(string.match(result, "time_connect=(%d+.%d%d%d)"))*1000
local ping_time = tonumber(string.match(result, "time_connect=(%d+.%d%d%d)"))
e.ping = ping_time and ping_time * 1000 or nil
else
-- TCP ping
local socket = nixio.socket("inet", "stream")
socket:setopt("socket", "rcvtimeo", 3)
socket:setopt("socket", "sndtimeo", 3)
e.socket = socket:connect(domain, port)
socket:close()
e.ping = luci.sys.exec(string.format("echo -n $(tcping -q -c 1 -i 1 -t 2 -p %s %s 2>&1 | grep -o 'time=[0-9]*' | awk -F '=' '{print $2}') 2>/dev/null", port, domain))
if (e.ping == "") then
e.ping = luci.sys.exec("echo -n $(ping -c 1 -W 1 %q 2>&1 | grep -o 'time=[0-9]*' | awk -F '=' '{print $2}') 2>/dev/null" % domain)
if (e.ping == "") then
-- UDP ping test using nping
e.ping = luci.sys.exec(string.format("echo -n $(nping --udp -c 1 -p %s %s 2>/dev/null | grep -o 'Avg rtt: [0-9.]*ms' | awk '{print $3}' | sed 's/ms//' | head -1) 2>/dev/null", port, domain))
e.ping = tonumber(luci.sys.exec(string.format(
"tcping -q -c 1 -i 1 -t 2 -p %d %s 2>/dev/null | grep -o 'time=[0-9]*' | awk -F '=' '{print $2}'",
port, domain
)))
if not e.ping then
e.ping = tonumber(luci.sys.exec(string.format(
"ping -c 1 -W 1 %s 2>/dev/null | grep -o 'time=[0-9]*' | awk -F '=' '{print $2}'",
domain
)))
end
if not e.ping then
e.ping = tonumber(luci.sys.exec(string.format(
"nping --udp -c 1 -p %d %s 2>/dev/null | grep -o 'Avg rtt: [0-9.]*ms' | awk '{print $3}' | sed 's/ms//' | head -1",
port, domain
)))
end
end
if iret then
if use_nft then
luci.sys.call("nft delete element inet ss_spec ss_spec_wan_ac { " .. domain .. " } 2>/dev/null")
else
luci.sys.call("ipset del ss_spec_wan_ac " .. domain .. " 2>/dev/null")
end
if (iret == 0) then
luci.sys.call(" ipset del ss_spec_wan_ac " .. domain)
end
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
@@ -101,28 +136,46 @@ function check_port()
local s
local server_name = ""
local uci = require "luci.model.uci".cursor()
local iret = 1
local use_nft = luci.sys.call("command -v nft >/dev/null") == 0
uci:foreach("shadowsocksr", "servers", function(s)
if s.alias then
server_name = s.alias
elseif s.server and s.server_port then
server_name = "%s:%s" % {s.server, s.server_port}
server_name = s.server .. ":" .. s.server_port
end
iret = luci.sys.call("ipset add ss_spec_wan_ac " .. s.server .. " 2>/dev/null")
socket = nixio.socket("inet", "stream")
-- 临时加入 set
local iret = false
if use_nft then
iret = luci.sys.call("nft add element inet ss_spec ss_spec_wan_ac { " .. s.server .. " } 2>/dev/null") == 0
else
iret = luci.sys.call("ipset add ss_spec_wan_ac " .. s.server .. " 2>/dev/null") == 0
end
-- TCP 测试
local socket = nixio.socket("inet", "stream")
socket:setopt("socket", "rcvtimeo", 3)
socket:setopt("socket", "sndtimeo", 3)
ret = socket:connect(s.server, s.server_port)
if tostring(ret) == "true" then
local ret = socket:connect(s.server, s.server_port)
socket:close()
retstring = retstring .. "<font><b style='color:green'>[" .. server_name .. "] OK.</b></font><br />"
if ret then
retstring = retstring .. string.format("<font><b style='color:green'>[%s] OK.</b></font><br />", server_name)
else
retstring = retstring .. "<font><b style='color:red'>[" .. server_name .. "] Error.</b></font><br />"
retstring = retstring .. string.format("<font><b style='color:red'>[%s] Error.</b></font><br />", server_name)
end
if iret == 0 then
-- 删除临时 set
if iret then
if use_nft then
luci.sys.call("nft delete element inet ss_spec ss_spec_wan_ac { " .. s.server .. " } 2>/dev/null")
else
luci.sys.call("ipset del ss_spec_wan_ac " .. s.server)
end
end
end)
luci.http.prepare_content("application/json")
luci.http.write_json({ret = retstring})
end

View File

@@ -4,14 +4,22 @@ local uci = require "luci.model.uci".cursor()
-- 获取 LAN IP 地址
function lanip()
local lan_ip
lan_ip = luci.sys.exec("uci -q get network.lan.ipaddr 2>/dev/null | awk -F '/' '{print $1}' | tr -d '\n'")
-- 尝试从 UCI 直接读取
lan_ip = luci.sys.exec("uci -q get network.lan.ipaddr 2>/dev/null | awk -F'/' '{print $1}' | tr -d '\\n'")
-- 尝试从 LAN 接口信息中读取(优先 ifname再 fallback 到 device
if not lan_ip or lan_ip == "" then
lan_ip = luci.sys.exec("ip address show $(uci -q -p /tmp/state get network.lan.ifname || uci -q -p /tmp/state get network.lan.device) | grep -w 'inet' | grep -Eo 'inet [0-9\.]+' | awk '{print $2}' | head -1 | tr -d '\n'")
lan_ip = luci.sys.exec([[
ip -4 addr show $(uci -q -p /tmp/state get network.lan.ifname || uci -q -p /tmp/state get network.lan.device) 2>/dev/null \
| grep -w 'inet' | awk '{print $2}' | cut -d'/' -f1 | grep -v '^127\.' | head -n1 | tr -d '\n']])
end
-- 取任意一个 global IPv4 地址
if not lan_ip or lan_ip == "" then
lan_ip = luci.sys.exec("ip addr show | grep -w 'inet' | grep 'global' | grep -Eo 'inet [0-9\.]+' | awk '{print $2}' | head -n 1 | tr -d '\n'")
lan_ip = luci.sys.exec([[
ip -4 addr show scope global 2>/dev/null \
| grep -w 'inet' | awk '{print $2}' | cut -d'/' -f1 | grep -v '^127\.' | head -n1 | tr -d '\n']])
end
return lan_ip

View File

@@ -264,7 +264,7 @@ s = m:section(NamedSection, sid, "servers")
s.anonymous = true
s.addremove = false
o = s:option(DummyValue, "ssr_url", "SS/SSR/V2RAY/TROJAN/HYSTERIA2 URL")
o = s:option(DummyValue, "ssr_url", "SS/SSR/V2RAY/TROJAN/TUIC/HYSTERIA2 URL")
o.rawhtml = true
o.template = "shadowsocksr/ssrurl"
o.value = sid
@@ -1285,15 +1285,26 @@ o = s:option(ListValue, "tuic_alpn", translate("TUIC ALPN"))
o.default = ""
o:value("", translate("Default"))
o:value("h3")
o:value("h2")
o:value("h3,h2")
o:value("spdy/3.1")
o:value("h3,spdy/3.1")
o:depends("type", "tuic")
-- IP STACK PREFERENCE
o = s:option(ListValue, "ipstack_prefer", translate("IP Stack Preference"))
o.default = ""
o:value("", translate("Default"))
o:value("v4first")
o:value("v6first")
o:depends("tuic_dual_stack", true)
-- [[ allowInsecure ]]--
o = s:option(Flag, "insecure", translate("allowInsecure"))
o.rmempty = false
o:depends("tls", true)
o:depends("type", "hysteria2")
o:depends("type", "tuic")
o.description = translate("If true, allowss insecure connection at TLS client, e.g., TLS server uses unverifiable certificates.")
-- [[ Hysteria2 TLS pinSHA256 ]] --

View File

@@ -8,14 +8,22 @@ local uci = require "luci.model.uci".cursor()
-- 获取 LAN IP 地址
function lanip()
local lan_ip
lan_ip = luci.sys.exec("uci -q get network.lan.ipaddr 2>/dev/null | awk -F '/' '{print $1}' | tr -d '\n'")
-- 尝试从 UCI 直接读取
lan_ip = luci.sys.exec("uci -q get network.lan.ipaddr 2>/dev/null | awk -F'/' '{print $1}' | tr -d '\\n'")
-- 尝试从 LAN 接口信息中读取(优先 ifname再 fallback 到 device
if not lan_ip or lan_ip == "" then
lan_ip = luci.sys.exec("ip address show $(uci -q -p /tmp/state get network.lan.ifname || uci -q -p /tmp/state get network.lan.device) | grep -w 'inet' | grep -Eo 'inet [0-9\.]+' | awk '{print $2}' | head -1 | tr -d '\n'")
lan_ip = luci.sys.exec([[
ip -4 addr show $(uci -q -p /tmp/state get network.lan.ifname || uci -q -p /tmp/state get network.lan.device) 2>/dev/null \
| grep -w 'inet' | awk '{print $2}' | cut -d'/' -f1 | grep -v '^127\.' | head -n1 | tr -d '\n']])
end
-- 取任意一个 global IPv4 地址
if not lan_ip or lan_ip == "" then
lan_ip = luci.sys.exec("ip addr show | grep -w 'inet' | grep 'global' | grep -Eo 'inet [0-9\.]+' | awk '{print $2}' | head -n 1 | tr -d '\n'")
lan_ip = luci.sys.exec([[
ip -4 addr show scope global 2>/dev/null \
| grep -w 'inet' | awk '{print $2}' | cut -d'/' -f1 | grep -v '^127\.' | head -n1 | tr -d '\n']])
end
return lan_ip

View File

@@ -75,9 +75,9 @@ function export_ssr_url(btn, urlname, sid) {
textarea.select();
try {
document.execCommand("copy"); // Security exception may be thrown by some browsers.
s.innerHTML = "<font color='green'><%:Copy SSR to clipboard successfully.%></font>";
s.innerHTML = "<font style=\'color:green\'><%:Copy SSR to clipboard successfully.%></font>";
} catch (ex) {
s.innerHTML = "<font color='red'><%:Unable to copy SSR to clipboard.%></font>";
s.innerHTML = "<font style=\'color:red\'><%:Unable to copy SSR to clipboard.%></font>";
} finally {
document.body.removeChild(textarea);
}
@@ -89,7 +89,7 @@ function import_ssr_url(btn, urlname, sid) {
if (!s) return false;
var ssrurl = prompt("<%:Paste sharing link here%>", "");
if (ssrurl == null || ssrurl == "") {
s.innerHTML = "<font color='red'><%:User cancelled.%></font>";
s.innerHTML = "<font style=\'color:red\'><%:User cancelled.%></font>";
return false;
}
s.innerHTML = "";
@@ -97,18 +97,6 @@ function import_ssr_url(btn, urlname, sid) {
ssrurl = ssrurl.replace(/&([a-zA-Z]+);/g, '&').replace(/\s*#\s*/, '#').trim(); //一些奇葩的链接用"&amp;"当做"&""#"前后带空格
var ssu = ssrurl.split('://');
//console.log(ssu.length);
if (ssu[0] === "ss") {
var queryStr = "";
if (ssu[1].indexOf("?") > -1) {
queryStr = ssu[1].split("?")[1]; // 提取 ? 后面的参数
}
var params = new URLSearchParams(queryStr);
if (params.get("type")) {
// 替换协议头
ssrurl = ssrurl.replace(/^ss:\/\//i, "shadowsocks://");
var ssu = ssrurl.split('://');
}
}
var event = document.createEvent("HTMLEvents");
event.initEvent("change", true, true);
switch (ssu[0]) {
@@ -189,14 +177,16 @@ function import_ssr_url(btn, urlname, sid) {
// 再分离 ? 或 /?(参数)
var queryIndex = (url0 = url0.replace('/?', '?')).indexOf("?");
var queryStr = "";
var query = "";
if (queryIndex >= 0) {
queryStr = url0.substring(queryIndex + 1);
query = url0.substring(queryIndex + 1);
url0 = url0.substring(0, queryIndex);
}
var params = Object.fromEntries(new URLSearchParams(queryStr));
var params = Object.fromEntries(new URLSearchParams(query));
if ( ! params.type) {
// 普通 SS 导入逻辑
// 判断是否 SIP002 格式(即含 @
if (url0.indexOf("@") !== -1) {
// === SIP002 格式 ===
@@ -319,6 +309,149 @@ function import_ssr_url(btn, urlname, sid) {
}
s.innerHTML = "<font style=\'color:green\'><%:Import configuration information successfully.%></font>";
return false;
} else {
try {
// Xray SS 导入逻辑
// 拆分 @,判断是否是 base64 userinfo 的格式
var parts = url0.split("@");
if (parts.length > 1) {
// @ 前是 base64(method:password),后面是 server:port?params
var userinfo = b64decsafe(parts[0]);
var sepIndex = userinfo.indexOf(":");
if (sepIndex > -1) {
method = userinfo.slice(0, sepIndex);
password = userinfo.slice(sepIndex + 1); //一些链接用明文uuid做密码
}
}
var url = new URL("http://" + url0 + (param ? "#" + encodeURIComponent(param) : ""));
} catch(e) {
alert(e);
return false;
}
// Check if the elements exist before trying to modify them
function setElementValue(name, value) {
const element = document.getElementsByName(name)[0];
if (element) {
if (typeof value === 'boolean') {
element.checked = value;
} else {
element.value = value;
}
}
}
function dispatchEventIfExists(name, event) {
const element = document.getElementsByName(name)[0];
if (element) {
element.dispatchEvent(event);
}
}
setElementValue('cbid.shadowsocksr.' + sid + '.alias', url.hash ? decodeURIComponent(url.hash.slice(1)) : "");
setElementValue('cbid.shadowsocksr.' + sid + '.type', "v2ray");
dispatchEventIfExists('cbid.shadowsocksr.' + sid + '.type', event);
setElementValue('cbid.shadowsocksr.' + sid + '.v2ray_protocol', "shadowsocks");
dispatchEventIfExists('cbid.shadowsocksr.' + sid + '.v2ray_protocol', event);
setElementValue('cbid.shadowsocksr.' + sid + '.server', url.hostname);
setElementValue('cbid.shadowsocksr.' + sid + '.server_port', url.port || "80");
setElementValue('cbid.shadowsocksr.' + sid + '.password', password || url.username);
setElementValue('cbid.shadowsocksr.' + sid + '.transport',
params.type === "http" ? "h2" :
(["xhttp", "splithttp"].includes(params.type) ? "xhttp" :
(["tcp", "raw"].includes(params.type) ? "raw" :
(params.type || "raw")))
);
dispatchEventIfExists('cbid.shadowsocksr.' + sid + '.transport', event);
setElementValue('cbid.shadowsocksr.' + sid + '.encrypt_method_ss', method || params.encryption || "none");
if ([ "tls", "xtls", "reality" ].includes(params.security)) {
setElementValue('cbid.shadowsocksr.' + sid + '.' + params.security, true);
dispatchEventIfExists('cbid.shadowsocksr.' + sid + '.' + params.security, event);
if (params.security === "tls") {
if (params.ech && params.ech.trim() !== "") {
setElementValue('cbid.shadowsocksr.' + sid + '.enable_ech', true); // 设置 enable_ech 为 true
dispatchEventIfExists('cbid.shadowsocksr.' + sid + '.enable_ech', event); // 触发事件
setElementValue('cbid.shadowsocksr.' + sid + '.ech_config', params.ech || "");
}
if (params.allowInsecure === "1") {
setElementValue('cbid.shadowsocksr.' + sid + '.insecure', true); // 设置 insecure 为 true
dispatchEventIfExists('cbid.shadowsocksr.' + sid + '.insecure', event); // 触发事件
}
}
if (params.security === "reality") {
setElementValue('cbid.shadowsocksr.' + sid + '.reality_publickey', params.pbk ? decodeURIComponent(params.pbk) : "");
setElementValue('cbid.shadowsocksr.' + sid + '.reality_shortid', params.sid || "");
setElementValue('cbid.shadowsocksr.' + sid + '.reality_spiderx', params.spx ? decodeURIComponent(params.spx) : "");
if (params.pqv && params.pqv.trim() !== "") {
setElementValue('cbid.shadowsocksr.' + sid + '.enable_mldsa65verify', true); // 设置 enable_mldsa65verify 为 true
dispatchEventIfExists('cbid.shadowsocksr.' + sid + '.enable_mldsa65verify', event); // 触发事件
setElementValue('cbid.shadowsocksr.' + sid + '.reality_mldsa65verify', params.pqv || "");
}
}
setElementValue('cbid.shadowsocksr.' + sid + '.tls_flow', params.flow || "none");
dispatchEventIfExists('cbid.shadowsocksr.' + sid + '.tls_flow', event);
setElementValue('cbid.shadowsocksr.' + sid + '.tls_alpn', params.alpn || "");
setElementValue('cbid.shadowsocksr.' + sid + '.fingerprint', params.fp || "");
setElementValue('cbid.shadowsocksr.' + sid + '.tls_host', params.sni || "");
}
switch (params.type) {
case "ws":
if (params.security !== "tls") {
setElementValue('cbid.shadowsocksr.' + sid + '.ws_host', params.host ? decodeURIComponent(params.host) : "");
}
setElementValue('cbid.shadowsocksr.' + sid + '.ws_path', params.path ? decodeURIComponent(params.path) : "/");
break;
case "httpupgrade":
if (params.security !== "tls") {
setElementValue('cbid.shadowsocksr.' + sid + '.httpupgrade_host', params.host ? decodeURIComponent(params.host) : "");
}
setElementValue('cbid.shadowsocksr.' + sid + '.httpupgrade_path', params.path ? decodeURIComponent(params.path) : "/");
break;
case "xhttp":
case "splithttp":
if (params.security !== "tls") {
setElementValue('cbid.shadowsocksr.' + sid + '.xhttp_host', params.host ? decodeURIComponent(params.host) : "");
}
setElementValue('cbid.shadowsocksr.' + sid + '.xhttp_mode', params.mode || "auto");
setElementValue('cbid.shadowsocksr.' + sid + '.xhttp_path', params.path ? decodeURIComponent(params.path) : "/");
if (params.extra && params.extra.trim() !== "") {
setElementValue('cbid.shadowsocksr.' + sid + '.enable_xhttp_extra', true); // 设置 enable_xhttp_extra 为 true
dispatchEventIfExists('cbid.shadowsocksr.' + sid + '.enable_xhttp_extra', event); // 触发事件
setElementValue('cbid.shadowsocksr.' + sid + '.xhttp_extra', params.extra || "");
}
break;
case "kcp":
setElementValue('cbid.shadowsocksr.' + sid + '.kcp_guise', params.headerType || "none");
setElementValue('cbid.shadowsocksr.' + sid + '.seed', params.seed || "");
break;
case "http":
/* this is non-standard, bullshit */
case "h2":
setElementValue('cbid.shadowsocksr.' + sid + '.h2_host', params.host ? decodeURIComponent(params.host) : "");
setElementValue('cbid.shadowsocksr.' + sid + '.h2_path', params.path ? decodeURIComponent(params.path) : "");
break;
case "quic":
setElementValue('cbid.shadowsocksr.' + sid + '.quic_guise', params.headerType || "none");
setElementValue('cbid.shadowsocksr.' + sid + '.quic_security', params.quicSecurity || "none");
setElementValue('cbid.shadowsocksr.' + sid + '.quic_key', params.key || "");
break;
case "grpc":
setElementValue('cbid.shadowsocksr.' + sid + '.serviceName', params.serviceName || "");
setElementValue('cbid.shadowsocksr.' + sid + '.grpc_mode', params.mode || "gun");
break;
case "tcp":
case "raw":
setElementValue('cbid.shadowsocksr.' + sid + '.tcp_guise', params.headerType || "none");
dispatchEventIfExists('cbid.shadowsocksr.' + sid + '.tcp_guise', event);
if (params.headerType === "http") {
setElementValue('cbid.shadowsocksr.' + sid + '.http_host', params.host ? decodeURIComponent(params.host) : "");
setElementValue('cbid.shadowsocksr.' + sid + '.http_path', params.path ? decodeURIComponent(params.path) : "");
}
break;
}
s.innerHTML = "<font style=\'color:green\'><%:Import configuration information successfully.%></font>";
return false;
}
case "ssr":
var sstr = b64decsafe((ssu[1] || "").replace(/#.*/, "").trim());
var ploc = sstr.indexOf("/?");
@@ -349,7 +482,7 @@ function import_ssr_url(btn, urlname, sid) {
document.getElementsByName('cbid.shadowsocksr.' + sid + '.protocol_param')[0].value = dictvalue(pdict, 'protoparam');
var rem = pdict['remarks'];
if (typeof (rem) != 'undefined' && rem != '' && rem.length > 0) document.getElementsByName('cbid.shadowsocksr.' + sid + '.alias')[0].value = b64decutf8safe(rem);
s.innerHTML = "<font color='green'><%:Import configuration information successfully.%></font>";
s.innerHTML = "<font style=\'color:green\'><%:Import configuration information successfully.%></font>";
return false;
case "trojan":
try {
@@ -360,6 +493,30 @@ function import_ssr_url(btn, urlname, sid) {
return false;
}
if (!params.get("type")) {
// 普通 Trojan 导入逻辑
document.getElementsByName('cbid.shadowsocksr.' + sid + '.alias')[0].value = url.hash ? decodeURIComponent(url.hash.slice(1)) : "";
document.getElementsByName('cbid.shadowsocksr.' + sid + '.type')[0].value = "trojan";
document.getElementsByName('cbid.shadowsocksr.' + sid + '.type')[0].dispatchEvent(event);
document.getElementsByName('cbid.shadowsocksr.' + sid + '.server')[0].value = url.hostname;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.server_port')[0].value = url.port || "80";
document.getElementsByName('cbid.shadowsocksr.' + sid + '.password')[0].value = decodeURIComponent(url.username);
document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls')[0].checked = true;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls')[0].dispatchEvent(event);
document.getElementsByName('cbid.shadowsocksr.' + sid + '.tls_host')[0].value = params.get("peer") || params.get("sni");
if (params.get("allowInsecure") === "1") {
document.getElementsByName('cbid.shadowsocksr.' + sid + '.insecure')[0].checked = true; // 设置 insecure 为 true
document.getElementsByName('cbid.shadowsocksr.' + sid + '.insecure')[0].dispatchEvent(event); // 触发事件
}
if (params.get("tfo") === "1") {
document.getElementsByName('cbid.shadowsocksr.' + sid + '.fast_open')[0].checked = true; // 设置 fast_open 为 true
document.getElementsByName('cbid.shadowsocksr.' + sid + '.fast_open')[0].dispatchEvent(event); // 触发事件
}
s.innerHTML = "<font style=\'color:green\'><%:Import configuration information successfully.%></font>";
return false;
} else {
// Xray Trojan 导入逻辑
document.getElementsByName('cbid.shadowsocksr.' + sid + '.alias')[0].value = url.hash ? decodeURIComponent(url.hash.slice(1)) : "";
document.getElementsByName('cbid.shadowsocksr.' + sid + '.type')[0].value = "v2ray";
document.getElementsByName('cbid.shadowsocksr.' + sid + '.type')[0].dispatchEvent(event);
@@ -379,7 +536,6 @@ function import_ssr_url(btn, urlname, sid) {
document.getElementsByName('cbid.shadowsocksr.' + sid + '.enable_ech')[0].checked = true; // 设置 enable_ech 为 true
document.getElementsByName('cbid.shadowsocksr.' + sid + '.enable_ech')[0].dispatchEvent(event); // 触发事件
document.getElementsByName('cbid.shadowsocksr.' + sid + '.ech_config')[0].value = params.get("ech");
}
document.getElementsByName('cbid.shadowsocksr.' + sid + '.transport')[0].value =
params.get("type") == "http" ? "h2" :
@@ -445,8 +601,9 @@ function import_ssr_url(btn, urlname, sid) {
break;
}
s.innerHTML = "<font color='green'><%:Import configuration information successfully.%></font>";
s.innerHTML = "<font style=\'color:green\'><%:Import configuration information successfully.%></font>";
return false;
}
case "vmess":
var sstr = b64DecodeUnicode((ssu[1] || "").replace(/#.*/, "").trim());
var ploc = sstr.indexOf("/?");
@@ -532,7 +689,7 @@ function import_ssr_url(btn, urlname, sid) {
document.getElementsByName('cbid.shadowsocksr.' + sid + '.mux')[0].checked = true;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.mux')[0].dispatchEvent(event);
}
s.innerHTML = "<font color='green'><%:Import configuration information successfully.%></font>";
s.innerHTML = "<font style=\'color:green\'><%:Import configuration information successfully.%></font>";
return false;
case "vless":
try {
@@ -664,153 +821,85 @@ function import_ssr_url(btn, urlname, sid) {
}
s.innerHTML = "<font style=\'color:green\'><%:Import configuration information successfully.%></font>";
return false;
case "shadowsocks":
try {
// 处理完整 ss:// 链接
var urlinfo = ssu[1];
// 拆分 @,判断是否是 base64 userinfo 的格式
var parts = urlinfo.split("@");
if (parts.length > 1) {
// @ 前是 base64(method:password),后面是 server:port?params
var userinfo = b64decsafe(parts[0]);
var sepIndex = userinfo.indexOf(":");
if (sepIndex > -1) {
method = userinfo.slice(0, sepIndex);
password = userinfo.slice(sepIndex + 1); //一些链接用明文uuid做密码
}
}
var url = new URL("http://" + urlinfo);
case "tuic":
var url0 = (ssu[1] || "");
var param = "";
var params = url.searchParams;
// 先分离 #alias
var hashIndex = url0.indexOf("#");
if (hashIndex >= 0) {
param = url0.substring(hashIndex + 1);
url0 = url0.substring(0, hashIndex);
}
} catch(e) {
alert(e);
return false;
// 再分离 ? 或 /?(参数)
var queryIndex = (url0 = url0.replace('/?', '?')).indexOf("?");
var query = "";
if (queryIndex >= 0) {
query = url0.substring(queryIndex + 1);
url0 = url0.substring(0, queryIndex);
}
// Check if the elements exist before trying to modify them
function setElementValue(name, value) {
const element = document.getElementsByName(name)[0];
if (element) {
if (typeof value === 'boolean') {
element.checked = value;
} else {
element.value = value;
}
}
}
function dispatchEventIfExists(name, event) {
const element = document.getElementsByName(name)[0];
if (element) {
element.dispatchEvent(event);
}
}
setElementValue('cbid.shadowsocksr.' + sid + '.alias', url.hash ? decodeURIComponent(url.hash.slice(1)) : "");
setElementValue('cbid.shadowsocksr.' + sid + '.type', "v2ray");
dispatchEventIfExists('cbid.shadowsocksr.' + sid + '.type', event);
setElementValue('cbid.shadowsocksr.' + sid + '.v2ray_protocol', "shadowsocks");
dispatchEventIfExists('cbid.shadowsocksr.' + sid + '.v2ray_protocol', event);
setElementValue('cbid.shadowsocksr.' + sid + '.server', url.hostname);
setElementValue('cbid.shadowsocksr.' + sid + '.server_port', url.port || "80");
setElementValue('cbid.shadowsocksr.' + sid + '.password', password || url.username);
setElementValue('cbid.shadowsocksr.' + sid + '.transport',
params.get("type") === "http" ? "h2" :
(["xhttp", "splithttp"].includes(params.get("type")) ? "xhttp" :
(["tcp", "raw"].includes(params.get("type")) ? "raw" :
(params.get("type") || "raw")))
);
dispatchEventIfExists('cbid.shadowsocksr.' + sid + '.transport', event);
setElementValue('cbid.shadowsocksr.' + sid + '.encrypt_method_ss', method || params.get("encryption") || "none");
if ([ "tls", "xtls", "reality" ].includes(params.get("security"))) {
setElementValue('cbid.shadowsocksr.' + sid + '.' + params.get("security"), true);
dispatchEventIfExists('cbid.shadowsocksr.' + sid + '.' + params.get("security"), event);
if (params.get("security") === "tls") {
if (params.get("ech") && params.get("ech").trim() !== "") {
setElementValue('cbid.shadowsocksr.' + sid + '.enable_ech', true); // 设置 enable_ech 为 true
dispatchEventIfExists('cbid.shadowsocksr.' + sid + '.enable_ech', event); // 触发事件
setElementValue('cbid.shadowsocksr.' + sid + '.ech_config', params.get("ech") || "");
}
if (params.get("allowInsecure") === "1") {
setElementValue('cbid.shadowsocksr.' + sid + '.insecure', true); // 设置 insecure 为 true
dispatchEventIfExists('cbid.shadowsocksr.' + sid + '.insecure', event); // 触发事件
}
}
if (params.get("security") === "reality") {
setElementValue('cbid.shadowsocksr.' + sid + '.reality_publickey', params.get("pbk") ? decodeURIComponent(params.get("pbk")) : "");
setElementValue('cbid.shadowsocksr.' + sid + '.reality_shortid', params.get("sid") || "");
setElementValue('cbid.shadowsocksr.' + sid + '.reality_spiderx', params.get("spx") ? decodeURIComponent(params.get("spx")) : "");
if (params.get("pqv") && params.get("pqv").trim() !== "") {
setElementValue('cbid.shadowsocksr.' + sid + '.enable_mldsa65verify', true); // 设置 enable_mldsa65verify 为 true
dispatchEventIfExists('cbid.shadowsocksr.' + sid + '.enable_mldsa65verify', event); // 触发事件
setElementValue('cbid.shadowsocksr.' + sid + '.reality_mldsa65verify', params.get("pqv") || "");
}
}
setElementValue('cbid.shadowsocksr.' + sid + '.tls_flow', params.get("flow") || "none");
dispatchEventIfExists('cbid.shadowsocksr.' + sid + '.tls_flow', event);
var params = Object.fromEntries(new URLSearchParams(query));
setElementValue('cbid.shadowsocksr.' + sid + '.tls_alpn', params.get("alpn") || "");
setElementValue('cbid.shadowsocksr.' + sid + '.fingerprint', params.get("fp") || "");
setElementValue('cbid.shadowsocksr.' + sid + '.tls_host', params.get("sni") || "");
}
switch (params.get("type")) {
case "ws":
if (params.get("security") !== "tls") {
setElementValue('cbid.shadowsocksr.' + sid + '.ws_host', params.get("host") ? decodeURIComponent(params.get("host")) : "");
}
setElementValue('cbid.shadowsocksr.' + sid + '.ws_path', params.get("path") ? decodeURIComponent(params.get("path")) : "/");
break;
case "httpupgrade":
if (params.get("security") !== "tls") {
setElementValue('cbid.shadowsocksr.' + sid + '.httpupgrade_host', params.get("host") ? decodeURIComponent(params.get("host")) : "");
}
setElementValue('cbid.shadowsocksr.' + sid + '.httpupgrade_path', params.get("path") ? decodeURIComponent(params.get("path")) : "/");
break;
case "xhttp":
case "splithttp":
if (params.get("security") !== "tls") {
setElementValue('cbid.shadowsocksr.' + sid + '.xhttp_host', params.get("host") ? decodeURIComponent(params.get("host")) : "");
}
setElementValue('cbid.shadowsocksr.' + sid + '.xhttp_mode', params.get("mode") || "auto");
setElementValue('cbid.shadowsocksr.' + sid + '.xhttp_path', params.get("path") ? decodeURIComponent(params.get("path")) : "/");
if (params.get("extra") && params.get("extra").trim() !== "") {
setElementValue('cbid.shadowsocksr.' + sid + '.enable_xhttp_extra', true); // 设置 enable_xhttp_extra 为 true
dispatchEventIfExists('cbid.shadowsocksr.' + sid + '.enable_xhttp_extra', event); // 触发事件
setElementValue('cbid.shadowsocksr.' + sid + '.xhttp_extra', params.get("extra") || "");
}
break;
case "kcp":
setElementValue('cbid.shadowsocksr.' + sid + '.kcp_guise', params.get("headerType") || "none");
setElementValue('cbid.shadowsocksr.' + sid + '.seed', params.get("seed") || "");
break;
case "http":
/* this is non-standard, bullshit */
case "h2":
setElementValue('cbid.shadowsocksr.' + sid + '.h2_host', params.get("host") ? decodeURIComponent(params.get("host")) : "");
setElementValue('cbid.shadowsocksr.' + sid + '.h2_path', params.get("path") ? decodeURIComponent(params.get("path")) : "");
break;
case "quic":
setElementValue('cbid.shadowsocksr.' + sid + '.quic_guise', params.get("headerType") || "none");
setElementValue('cbid.shadowsocksr.' + sid + '.quic_security', params.get("quicSecurity") || "none");
setElementValue('cbid.shadowsocksr.' + sid + '.quic_key', params.get("key") || "");
break;
case "grpc":
setElementValue('cbid.shadowsocksr.' + sid + '.serviceName', params.get("serviceName") || "");
setElementValue('cbid.shadowsocksr.' + sid + '.grpc_mode', params.get("mode") || "gun");
break;
case "tcp":
case "raw":
setElementValue('cbid.shadowsocksr.' + sid + '.tcp_guise', params.get("headerType") || "none");
dispatchEventIfExists('cbid.shadowsocksr.' + sid + '.tcp_guise', event);
if (params.get("headerType") === "http") {
setElementValue('cbid.shadowsocksr.' + sid + '.http_host', params.get("host") ? decodeURIComponent(params.get("host")) : "");
setElementValue('cbid.shadowsocksr.' + sid + '.http_path', params.get("path") ? decodeURIComponent(params.get("path")) : "");
}
var sipIndex = url0.indexOf("@");
var userInfo = url0.substring(0, sipIndex); // 格式uuid:password
var hostPart = url0.substring(sipIndex + 1); // 格式hostname:port
var userInfoSplitIndex = userInfo.indexOf(":");
if(userInfoSplitIndex < 0) {
// 格式错误
s.innerHTML = "<font style='color:red'><%:Userinfo format error.%></font>";
break;
}
s.innerHTML = "<font color='green'><%:Import configuration information successfully.%></font>";
var method = userInfo.substring(0, userInfoSplitIndex);
var password = userInfo.substring(userInfoSplitIndex + 1);
var url = new URL("http://" + hostPart); // 用 URL 提取 host 与 port
document.getElementsByName('cbid.shadowsocksr.' + sid + '.type')[0].value = ssu[0];
document.getElementsByName('cbid.shadowsocksr.' + sid + '.type')[0].dispatchEvent(event);
document.getElementsByName('cbid.shadowsocksr.' + sid + '.server')[0].value = url.hostname;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.server_port')[0].value = url.port;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.tuic_uuid')[0].value = method;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.tuic_ip')[0].value = params.ip || "";
document.getElementsByName('cbid.shadowsocksr.' + sid + '.tuic_passwd')[0].value = password;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.udp_relay_mode')[0].value = params.udp_relay_mode || "native";
document.getElementsByName('cbid.shadowsocksr.' + sid + '.congestion_control')[0].value = params.congestion_control || "cubic";
document.getElementsByName('cbid.shadowsocksr.' + sid + '.tuic_alpn')[0].value = params.alpn || "";
document.getElementsByName('cbid.shadowsocksr.' + sid + '.heartbeat')[0].value = params.heartbeat || "3";
document.getElementsByName('cbid.shadowsocksr.' + sid + '.timeout')[0].value = params.timeout || "8";
document.getElementsByName('cbid.shadowsocksr.' + sid + '.gc_interval')[0].value = params.gc_interval || "3";
document.getElementsByName('cbid.shadowsocksr.' + sid + '.gc_lifetime')[0].value = params.gc_lifetime || "15";
document.getElementsByName('cbid.shadowsocksr.' + sid + '.send_window')[0].value = params.send_window || "20971520";
document.getElementsByName('cbid.shadowsocksr.' + sid + '.receive_window')[0].value = params.receive_window || "10485760";
document.getElementsByName('cbid.shadowsocksr.' + sid + '.tuic_max_package_size')[0].value = params.max_packet_size || "1500";
if (params["disable_sni"] === "1" || params["disable_sni"] === "true") {
document.getElementsByName('cbid.shadowsocksr.' + sid + '.disable_sni')[0].checked = true;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.disable_sni')[0].dispatchEvent(event);
}
if (params["zero_rtt_handshake"] === "1" || params["zero_rtt_handshake"] === "true") {
document.getElementsByName('cbid.shadowsocksr.' + sid + '.zero_rtt_handshake')[0].checked = true;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.zero_rtt_handshake')[0].dispatchEvent(event);
}
if (params["dual_stack"] === "1" || params["dual_stack"] === "true") {
document.getElementsByName('cbid.shadowsocksr.' + sid + '.tuic_dual_stack')[0].checked = true;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.tuic_dual_stack')[0].dispatchEvent(event);
if (params.ipstack_prefer && params.ipstack_prefer.trim() !== "") {
document.getElementsByName('cbid.shadowsocksr.' + sid + '.ipstack_prefer')[0].value = params.ipstack_prefer;
}
}
if (params["allowInsecure"] === "1" || params["allowInsecure"] === "true") {
document.getElementsByName('cbid.shadowsocksr.' + sid + '.insecure')[0].checked = true;
document.getElementsByName('cbid.shadowsocksr.' + sid + '.insecure')[0].dispatchEvent(event);
}
if (param != undefined) {
document.getElementsByName('cbid.shadowsocksr.' + sid + '.alias')[0].value = decodeURIComponent(param);
}
s.innerHTML = "<font style=\'color:green\'><%:Import configuration information successfully.%></font>";
return false;
default:
s.innerHTML = "<font color='red'><%:Invalid format.%></font>";
s.innerHTML = "<font style=\'color:red\'><%:Invalid format.%></font>";
return false;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1258,8 +1258,18 @@ start_server() {
[ "$(uci_get_by_name $1 enable 0)" == "0" ] && return 1
let server_count=server_count+1
if [ "$server_count" == "1" ]; then
if ! (iptables-save -t filter | grep SSR-SERVER-RULE >/dev/null); then
iptables -N SSR-SERVER-RULE && iptables -t filter -I INPUT -j SSR-SERVER-RULE
if command -v nft >/dev/null 2>&1; then
# nftables / fw4
if ! nft list chain inet fw4 SSR-SERVER-RULE >/dev/null 2>&1; then
nft add chain inet fw4 SSR-SERVER-RULE
nft insert rule inet fw4 input jump SSR-SERVER-RULE
fi
else
# iptables / fw3
if ! (iptables-save -t filter | grep -q "SSR-SERVER-RULE"); then
iptables -N SSR-SERVER-RULE
iptables -t filter -I INPUT -j SSR-SERVER-RULE
fi
fi
fi
local type=$(uci_get_by_name $1 type)
@@ -1287,17 +1297,15 @@ start_server() {
echolog "Server:Socks5 Server$server_count Started!"
;;
esac
ssr_server_port=$(uci show shadowsocksr | grep 'server_config.*server_port' | awk -F"'" '{print $2}' | tr "\n" " ")
if [ -n "$ssr_server_port" ]; then
uci -q delete firewall.shadowsocksr_server
uci set firewall.shadowsocksr_server=rule
uci set firewall.shadowsocksr_server.name="shadowsocksr_server"
uci set firewall.shadowsocksr_server.target="ACCEPT"
uci set firewall.shadowsocksr_server.src="wan"
uci set firewall.shadowsocksr_server.dest_port="$ssr_server_port"
uci set firewall.shadowsocksr_server.enabled="1"
uci commit firewall
/etc/init.d/firewall reload >/dev/null 2>&1
server_port=$(uci_get_by_name $1 server_port)
if command -v nft >/dev/null 2>&1; then
# nftables / fw4
nft add rule inet fw4 SSR-SERVER-RULE tcp dport $server_port accept
nft add rule inet fw4 SSR-SERVER-RULE udp dport $server_port accept
else
# iptables / fw3
iptables -t filter -A SSR-SERVER-RULE -p tcp --dport $server_port -j ACCEPT
iptables -t filter -A SSR-SERVER-RULE -p udp --dport $server_port -j ACCEPT
fi
return 0
}
@@ -1307,6 +1315,25 @@ start_server() {
if [ ! -f $FWI ]; then
echo '#!/bin/sh' >$FWI
fi
if command -v nft >/dev/null 2>&1; then
# nftables / fw4
extract_rules() {
nft list chain inet fw4 SSR-SERVER-RULE 2>/dev/null | \
grep -v 'chain SSR-SERVER-RULE' | grep -v '^\s*{' | grep -v '^\s*}' | sed 's/ counter//g'
}
cat <<-EOF >>$FWI
nft flush chain inet fw4 SSR-SERVER-RULE 2>/dev/null || true
nft -f - <<-EOT
table inet fw4 {
chain SSR-SERVER-RULE {
type filter hook input priority 0; policy accept;
$(extract_rules)
}
}
EOT
EOF
else
# iptables / fw3
extract_rules() {
echo "*filter"
iptables-save -t filter | grep SSR-SERVER-RULE | sed -e "s/^-A INPUT/-I INPUT/"
@@ -1318,6 +1345,7 @@ start_server() {
$(extract_rules)
EOT
EOF
fi
}
config_load $NAME
@@ -1455,6 +1483,28 @@ stop() {
unlock
set_lock
/usr/bin/ssr-rules -f
if command -v nft >/dev/null 2>&1; then
# nftables / fw4
#local srulecount=$(nft list ruleset 2>/dev/null | grep -c 'SSR-SERVER-RULE')
#local srulecount=$(nft list chain inet fw4 SSR-SERVER-RULE 2>/dev/null | grep -c 'dport')
local srulecount=$(nft list chain inet fw4 SSR-SERVER-RULE | grep -vE '^\s*(chain|{|})' | wc -l)
else
# iptables / fw3
local srulecount=$(iptables -L | grep SSR-SERVER-RULE | wc -l)
fi
if [ $srulecount -gt 0 ]; then
if command -v nft >/dev/null 2>&1; then
# nftables / fw4
nft flush chain inet fw4 SSR-SERVER-RULE 2>/dev/null || true
nft delete rule inet fw4 input jump SSR-SERVER-RULE 2>/dev/null || true
nft delete chain inet fw4 SSR-SERVER-RULE 2>/dev/null || true
else
# iptables / fw3
iptables -F SSR-SERVER-RULE
iptables -t filter -D INPUT -j SSR-SERVER-RULE
iptables -X SSR-SERVER-RULE 2>/dev/null
fi
fi
if [ -z "$switch_server" ]; then
$PS -w | grep -v "grep" | grep ssr-switch | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 &
rm -f /var/lock/ssr-switch.lock
@@ -1465,7 +1515,7 @@ stop() {
( \
# Graceful kill first, so programs have the chance to stop its subprocesses
$PS -w | grep -v "grep" | grep "$TMP_PATH" | awk '{print $1}' | xargs kill >/dev/null 2>&1 ; \
sleep 1s; \
sleep 3s; \
# Force kill hanged programs
$PS -w | grep -v "grep" | grep "$TMP_PATH" | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 ; \
)
@@ -1488,9 +1538,6 @@ stop() {
/etc/init.d/dnsmasq restart >/dev/null 2>&1
fi
uci -q delete firewall.shadowsocksr_server
uci commit firewall
/etc/init.d/firewall reload >/dev/null 2>&1
del_cron
unset_lock
}

View File

@@ -1,37 +1,7 @@
aaplimg.com
account.synology.com
apple-cloudkit.com
apple.co
apple.com
apple.com.cn
appstore.com
bilibili.com
bilibili.cn
bilivideo.com
bilivideo.cn
biliapi.com
biliapi.net
bilibili.cn
bilibili.com
bilivideo.cn
bilivideo.com
bing.com
cdn-apple.com
checkip.dyndns.org
checkip.synology.com
checkipv6.synology.com
checkport.synology.com
crashlytics.com
ddns.synology.com
gitmirror.com
icloud-content.com
icloud.com
icloud.com.cn
images-cn.ssl-images-amazon.com
mirrorlist.centos.org
mzstatic.com
office365.com
officecdn-microsoft-com.akamaized.net
teamviewer.com
whatismyip.akamai.com
windows.com
windowsupdate.com
worldbank.org
worldscientific.com
www-cdn.icloud.com.akadns.net
apple.com

View File

@@ -9,12 +9,12 @@
# Detect firewall version and set appropriate tools
detect_firewall() {
if command -v fw4 >/dev/null 2>&1 && [ -f /usr/share/nftables.d/ruleset-post/99-shadowsocksr.nft ]; then
USE_NFT=1
NFT="nft"
elif command -v nft >/dev/null 2>&1 && [ "$(uci get firewall.@defaults[0].syn_flood 2>/dev/null)" != "" ] && [ ! -f /etc/config/firewall3 ]; then
if command -v nft >/dev/null 2>&1 && \
[ -n "$(uci get firewall.@defaults[0].syn_flood 2>/dev/null)" ] && \
! grep -q "fw3" /etc/init.d/firewall 2>/dev/null; then
USE_NFT=1
NFT="nft"
FWI=$(uci get firewall.shadowsocksr.path 2>/dev/null) # firewall include file
else
USE_NFT=0
IPT="iptables -t nat" # alias of iptables
@@ -26,6 +26,7 @@ detect_firewall() {
detect_firewall
TAG="_SS_SPEC_RULE_" # comment tag
usage() {
cat <<-EOF
Usage: ssr-rules [options]
@@ -83,11 +84,15 @@ flush_r() {
flush_nftables() {
# Remove nftables rules and sets
$NFT delete table inet ss_spec 2>/dev/null
$NFT delete table ip ss_spec 2>/dev/null
$NFT delete table ip ss_spec_mangle 2>/dev/null
# Clean up routing rules
ip rule del fwmark 0x01/0x01 table 100 2>/dev/null
ip route del local 0.0.0.0/0 dev lo table 100 2>/dev/null
[ -n "$FWI" ] && echo '#!/bin/sh' >"$FWI"
return 0
}
@@ -128,43 +133,43 @@ ipset_r() {
}
ipset_nft() {
[ -f "$IGNORE_LIST" ] && /usr/share/shadowsocksr/chinaipset.sh $IGNORE_LIST
[ -f "$IGNORE_LIST" ] && /usr/share/shadowsocksr/chinaipset.sh "$IGNORE_LIST"
# Create nftables table and sets
$NFT add table inet ss_spec 2>/dev/null
$NFT add set inet ss_spec ss_spec_wan_ac { type ipv4_addr\; flags interval\; } 2>/dev/null
$NFT add set inet ss_spec gmlan { type ipv4_addr\; flags interval\; } 2>/dev/null
$NFT add set inet ss_spec fplan { type ipv4_addr\; flags interval\; } 2>/dev/null
$NFT add set inet ss_spec bplan { type ipv4_addr\; flags interval\; } 2>/dev/null
$NFT add set inet ss_spec whitelist { type ipv4_addr\; flags interval\; } 2>/dev/null
$NFT add set inet ss_spec blacklist { type ipv4_addr\; flags interval\; } 2>/dev/null
$NFT add set inet ss_spec netflix { type ipv4_addr\; flags interval\; } 2>/dev/null
$NFT add set inet ss_spec ss_spec_wan_ac '{ type ipv4_addr; flags interval; }' 2>/dev/null
$NFT add set inet ss_spec gmlan '{ type ipv4_addr; flags interval; }' 2>/dev/null
$NFT add set inet ss_spec fplan '{ type ipv4_addr; flags interval; }' 2>/dev/null
$NFT add set inet ss_spec bplan '{ type ipv4_addr; flags interval; }' 2>/dev/null
$NFT add set inet ss_spec whitelist '{ type ipv4_addr; flags interval; }' 2>/dev/null
$NFT add set inet ss_spec blacklist '{ type ipv4_addr; flags interval; }' 2>/dev/null
$NFT add set inet ss_spec netflix '{ type ipv4_addr; flags interval; }' 2>/dev/null
# Add IP addresses to sets
for ip in $LAN_GM_IP; do
$NFT add element inet ss_spec gmlan { $ip }
$NFT add element inet ss_spec gmlan "{ $ip }"
done
for ip in $LAN_FP_IP; do
$NFT add element inet ss_spec fplan { $ip }
$NFT add element inet ss_spec fplan "{ $ip }"
done
for ip in $LAN_BP_IP; do
$NFT add element inet ss_spec bplan { $ip }
$NFT add element inet ss_spec bplan "{ $ip }"
done
for ip in $WAN_BP_IP; do
$NFT add element inet ss_spec whitelist { $ip }
$NFT add element inet ss_spec whitelist "{ $ip }"
done
for ip in $WAN_FW_IP; do
$NFT add element inet ss_spec blacklist { $ip }
$NFT add element inet ss_spec blacklist "{ $ip }"
done
# Create main chain for WAN access control
$NFT add chain inet ss_spec ss_spec_wan_ac { type nat hook prerouting priority dstnat\; }
$NFT add chain inet ss_spec ss_spec_wan_ac '{ type nat hook prerouting priority dstnat; }' 2>/dev/null
$NFT add rule inet ss_spec ss_spec_wan_ac tcp dport 53 ip daddr 127.0.0.0/8 return
$NFT add rule inet ss_spec ss_spec_wan_ac tcp dport != 53 ip daddr $server return
$NFT add rule inet ss_spec ss_spec_wan_ac tcp dport != 53 ip daddr "$server" return
# Add special IP ranges to WAN AC set
for ip in $(gen_spec_iplist); do
$NFT add element inet ss_spec ss_spec_wan_ac { $ip }
$NFT add element inet ss_spec ss_spec_wan_ac "{ $ip }"
done
# Set up mode-specific rules
@@ -212,19 +217,19 @@ ipset_nft() {
# Shunt/Netflix rules
if [ "$SHUNT_PORT" != "0" ]; then
for ip in $(cat ${SHUNT_LIST:=/dev/null} 2>/dev/null); do
$NFT add element inet ss_spec netflix { $ip }
for ip in $(cat "${SHUNT_LIST:=/dev/null}" 2>/dev/null); do
$NFT add element inet ss_spec netflix "{ $ip }"
done
case "$SHUNT_PORT" in
1)
$NFT add rule inet ss_spec ss_spec_wan_ac tcp dport $PROXY_PORTS ip daddr @netflix redirect to :$local_port
$NFT add rule inet ss_spec ss_spec_wan_ac tcp dport "$PROXY_PORTS" ip daddr @netflix redirect to :"$local_port"
;;
*)
$NFT add rule inet ss_spec ss_spec_wan_ac tcp dport $PROXY_PORTS ip daddr @netflix redirect to :$SHUNT_PORT
if [ "$SHUNT_PROXY" == "1" ]; then
$NFT add rule inet ss_spec ss_spec_wan_ac tcp dport $PROXY_PORTS ip daddr $SHUNT_IP redirect to :$local_port
$NFT add rule inet ss_spec ss_spec_wan_ac tcp dport "$PROXY_PORTS" ip daddr @netflix redirect to :"$SHUNT_PORT"
if [ "$SHUNT_PROXY" = "1" ]; then
$NFT add rule inet ss_spec ss_spec_wan_ac tcp dport "$PROXY_PORTS" ip daddr "$SHUNT_IP" redirect to :"$local_port"
else
$NFT add element inet ss_spec whitelist { $SHUNT_IP }
$NFT add element inet ss_spec whitelist "{ $SHUNT_IP }"
fi
;;
esac
@@ -233,12 +238,12 @@ ipset_nft() {
}
ipset_iptables() {
[ -f "$IGNORE_LIST" ] && /usr/share/shadowsocksr/chinaipset.sh $IGNORE_LIST
[ -f "$IGNORE_LIST" ] && /usr/share/shadowsocksr/chinaipset.sh "$IGNORE_LIST"
$IPT -N SS_SPEC_WAN_AC 2>/dev/null
$IPT -I SS_SPEC_WAN_AC -p tcp --dport 53 -d 127.0.0.0/8 -j RETURN
$IPT -I SS_SPEC_WAN_AC -p tcp ! --dport 53 -d $server -j RETURN
$IPT -I SS_SPEC_WAN_AC -p tcp ! --dport 53 -d "$server" -j RETURN
ipset -N gmlan hash:net 2>/dev/null
for ip in $LAN_GM_IP; do ipset -! add gmlan $ip; done
for ip in $LAN_GM_IP; do ipset -! add gmlan "$ip"; done
case "$RUNMODE" in
router)
ipset -! -R <<-EOF || return 1
@@ -267,34 +272,34 @@ ipset_iptables() {
;;
esac
ipset -N fplan hash:net 2>/dev/null
for ip in $LAN_FP_IP; do ipset -! add fplan $ip; done
for ip in $LAN_FP_IP; do ipset -! add fplan "$ip"; done
$IPT -I SS_SPEC_WAN_AC -m set --match-set fplan src -j SS_SPEC_WAN_FW
ipset -N bplan hash:net 2>/dev/null
for ip in $LAN_BP_IP; do ipset -! add bplan $ip; done
for ip in $LAN_BP_IP; do ipset -! add bplan "$ip"; done
$IPT -I SS_SPEC_WAN_AC -m set --match-set bplan src -j RETURN
ipset -N whitelist hash:net 2>/dev/null
ipset -N blacklist hash:net 2>/dev/null
$IPT -I SS_SPEC_WAN_AC -m set --match-set blacklist dst -j SS_SPEC_WAN_FW
$IPT -I SS_SPEC_WAN_AC -m set --match-set whitelist dst -j RETURN
if [ $(ipset list music -name -quiet | grep music) ]; then
if ipset list music -name -quiet >/dev/null 2>&1; then
$IPT -I SS_SPEC_WAN_AC -m set --match-set music dst -j RETURN 2>/dev/null
fi
for ip in $WAN_BP_IP; do ipset -! add whitelist $ip; done
for ip in $WAN_FW_IP; do ipset -! add blacklist $ip; done
for ip in $WAN_BP_IP; do ipset -! add whitelist "$ip"; done
for ip in $WAN_FW_IP; do ipset -! add blacklist "$ip"; done
if [ "$SHUNT_PORT" != "0" ]; then
ipset -N netflix hash:net 2>/dev/null
for ip in $(cat ${SHUNT_LIST:=/dev/null} 2>/dev/null); do ipset -! add netflix $ip; done
for ip in $(cat "${SHUNT_LIST:=/dev/null}" 2>/dev/null); do ipset -! add netflix "$ip"; done
case "$SHUNT_PORT" in
0) ;;
1)
$IPT -I SS_SPEC_WAN_AC -p tcp -m set --match-set netflix dst -j REDIRECT --to-ports $local_port
$IPT -I SS_SPEC_WAN_AC -p tcp -m set --match-set netflix dst -j REDIRECT --to-ports "$local_port"
;;
*)
$IPT -I SS_SPEC_WAN_AC -p tcp -m set --match-set netflix dst -j REDIRECT --to-ports $SHUNT_PORT
if [ "$SHUNT_PROXY" == "1" ]; then
$IPT -I SS_SPEC_WAN_AC -p tcp -d $SHUNT_IP -j REDIRECT --to-ports $local_port
$IPT -I SS_SPEC_WAN_AC -p tcp -m set --match-set netflix dst -j REDIRECT --to-ports "$SHUNT_PORT"
if [ "$SHUNT_PROXY" = "1" ]; then
$IPT -I SS_SPEC_WAN_AC -p tcp -d "$SHUNT_IP" -j REDIRECT --to-ports "$local_port"
else
ipset -! add whitelist $SHUNT_IP
ipset -! add whitelist "$SHUNT_IP"
fi
;;
esac
@@ -312,28 +317,38 @@ fw_rule() {
}
fw_rule_nft() {
# Create forward chain for nftables
$NFT add chain inet ss_spec ss_spec_wan_fw
$NFT add rule inet ss_spec ss_spec_wan_fw ip daddr 0.0.0.0/8 return
$NFT add rule inet ss_spec ss_spec_wan_fw ip daddr 10.0.0.0/8 return
$NFT add rule inet ss_spec ss_spec_wan_fw ip daddr 127.0.0.0/8 return
$NFT add rule inet ss_spec ss_spec_wan_fw ip daddr 169.254.0.0/16 return
$NFT add rule inet ss_spec ss_spec_wan_fw ip daddr 172.16.0.0/12 return
$NFT add rule inet ss_spec ss_spec_wan_fw ip daddr 192.168.0.0/16 return
$NFT add rule inet ss_spec ss_spec_wan_fw ip daddr 224.0.0.0/4 return
$NFT add rule inet ss_spec ss_spec_wan_fw ip daddr 240.0.0.0/4 return
# Create forward chain with better error handling
if ! $NFT list chain inet ss_spec ss_spec_wan_fw >/dev/null 2>&1; then
$NFT add chain inet ss_spec ss_spec_wan_fw 2>/dev/null || {
loger 3 "Failed to create forward chain"
return 1
}
fi
# Exclude special local addresses
$NFT add rule inet ss_spec ss_spec_wan_fw ip daddr 0.0.0.0/8 return 2>/dev/null
$NFT add rule inet ss_spec ss_spec_wan_fw ip daddr 10.0.0.0/8 return 2>/dev/null
$NFT add rule inet ss_spec ss_spec_wan_fw ip daddr 127.0.0.0/8 return 2>/dev/null
$NFT add rule inet ss_spec ss_spec_wan_fw ip daddr 169.254.0.0/16 return 2>/dev/null
$NFT add rule inet ss_spec ss_spec_wan_fw ip daddr 172.16.0.0/12 return 2>/dev/null
$NFT add rule inet ss_spec ss_spec_wan_fw ip daddr 192.168.0.0/16 return 2>/dev/null
$NFT add rule inet ss_spec ss_spec_wan_fw ip daddr 224.0.0.0/4 return 2>/dev/null
$NFT add rule inet ss_spec ss_spec_wan_fw ip daddr 240.0.0.0/4 return 2>/dev/null
# redirect/translation: when PROXY_PORTS present, redirect those tcp ports to local_port
if [ -n "$PROXY_PORTS" ]; then
$NFT add rule inet ss_spec ss_spec_wan_fw tcp $PROXY_PORTS redirect to :$local_port 2>/dev/null || {
$NFT add rule inet ss_spec ss_spec_wan_fw tcp dport "$PROXY_PORTS" redirect to :"$local_port" 2>/dev/null || {
loger 3 "Can't redirect, please check nftables."
exit 1
}
else
$NFT add rule inet ss_spec ss_spec_wan_fw tcp dport != 22 redirect to :$local_port 2>/dev/null || {
# default: redirect everything except ssh(22)
$NFT add rule inet ss_spec ss_spec_wan_fw tcp dport != 22 redirect to :"$local_port" 2>/dev/null || {
loger 3 "Can't redirect, please check nftables."
exit 1
}
fi
return 0
}
@@ -347,7 +362,7 @@ fw_rule_iptables() {
$IPT -A SS_SPEC_WAN_FW -d 192.168.0.0/16 -j RETURN
$IPT -A SS_SPEC_WAN_FW -d 224.0.0.0/4 -j RETURN
$IPT -A SS_SPEC_WAN_FW -d 240.0.0.0/4 -j RETURN
$IPT -A SS_SPEC_WAN_FW -p tcp $PROXY_PORTS -j REDIRECT --to-ports $local_port 2>/dev/null || {
$IPT -A SS_SPEC_WAN_FW -p tcp $PROXY_PORTS -j REDIRECT --to-ports "$local_port" 2>/dev/null || {
loger 3 "Can't redirect, please check the iptables."
exit 1
}
@@ -366,13 +381,13 @@ ac_rule() {
ac_rule_nft() {
local MATCH_SET_CONDITION=""
if [ -n "$LAN_AC_IP" ]; then
# Create LAN access control set
$NFT add set inet ss_spec ss_spec_lan_ac { type ipv4_addr\; flags interval\; } 2>/dev/null
for ip in ${LAN_AC_IP:1}; do
$NFT add element inet ss_spec ss_spec_lan_ac { $ip }
# Create LAN access control set if needed
$NFT add set inet ss_spec ss_spec_lan_ac '{ type ipv4_addr; flags interval; }' 2>/dev/null
for ip in ${LAN_AC_IP#?}; do
[ -n "$ip" ] && $NFT add element inet ss_spec ss_spec_lan_ac "{ $ip }" 2>/dev/null
done
case "${LAN_AC_IP:0:1}" in
case "${LAN_AC_IP%${LAN_AC_IP#?}}" in
w | W)
MATCH_SET_CONDITION="ip saddr @ss_spec_lan_ac"
;;
@@ -386,22 +401,23 @@ ac_rule_nft() {
esac
fi
# Create prerouting rules
# Build a rule in the prerouting hook chain that jumps to business chain with conditions
if [ -z "$Interface" ]; then
# generic prerouting jump already exists (see ipset_nft), but if we have MATCH_SET_CONDITION we add a more specific rule
if [ -n "$MATCH_SET_CONDITION" ]; then
$NFT add rule inet ss_spec ss_spec_wan_ac tcp dport $EXT_ARGS $MATCH_SET_CONDITION comment "\"$TAG\"" goto ss_spec_wan_ac
else
$NFT add rule inet ss_spec ss_spec_wan_ac tcp dport $EXT_ARGS comment "\"$TAG\"" goto ss_spec_wan_ac
# add a more specific rule at the top of ss_spec_prerouting
$NFT insert rule inet ss_spec ss_spec_prerouting tcp $MATCH_SET_CONDITION comment "\"$TAG\"" jump ss_spec_wan_ac 2>/dev/null
fi
else
# For each Interface, find its actual ifname and add an iifname-limited prerouting rule
for name in $Interface; do
local IFNAME=$(uci -P /var/state get network.$name.ifname 2>/dev/null)
[ -z "$IFNAME" ] && IFNAME=$(uci -P /var/state get network.$name.device 2>/dev/null)
local IFNAME=$(uci -P /var/state get network."$name".ifname 2>/dev/null)
[ -z "$IFNAME" ] && IFNAME=$(uci -P /var/state get network."$name".device 2>/dev/null)
if [ -n "$IFNAME" ]; then
if [ -n "$MATCH_SET_CONDITION" ]; then
$NFT add rule inet ss_spec ss_spec_wan_ac iifname $IFNAME tcp dport $EXT_ARGS $MATCH_SET_CONDITION comment "\"$TAG\"" goto ss_spec_wan_ac
$NFT insert rule inet ss_spec ss_spec_prerouting iifname "$IFNAME" tcp $MATCH_SET_CONDITION comment "\"$TAG\"" jump ss_spec_wan_ac 2>/dev/null
else
$NFT add rule inet ss_spec ss_spec_wan_ac iifname $IFNAME tcp dport $EXT_ARGS comment "\"$TAG\"" goto ss_spec_wan_ac
$NFT insert rule inet ss_spec ss_spec_prerouting iifname "$IFNAME" tcp comment "\"$TAG\"" jump ss_spec_wan_ac 2>/dev/null
fi
fi
done
@@ -409,21 +425,21 @@ ac_rule_nft() {
case "$OUTPUT" in
1)
# Add output rules
$NFT add chain inet ss_spec ss_spec_output { type nat hook output priority dstnat\; }
$NFT add rule inet ss_spec ss_spec_output tcp dport $EXT_ARGS comment "\"$TAG\"" goto ss_spec_wan_ac
# create output hook chain & route output traffic into router chain
$NFT add chain inet ss_spec ss_spec_output '{ type nat hook output priority dstnat; }' 2>/dev/null
$NFT add rule inet ss_spec ss_spec_output tcp comment "\"$TAG\"" jump ss_spec_wan_ac 2>/dev/null
;;
2)
# Router mode output rules
$NFT add set inet ss_spec ssr_gen_router { type ipv4_addr\; flags interval\; } 2>/dev/null
# router mode output chain: create ssr_gen_router set & router chain
$NFT add set inet ss_spec ssr_gen_router '{ type ipv4_addr; flags interval; }' 2>/dev/null
for ip in $(gen_spec_iplist); do
$NFT add element inet ss_spec ssr_gen_router { $ip }
[ -n "$ip" ] && $NFT add element inet ss_spec ssr_gen_router "{ $ip }" 2>/dev/null
done
$NFT add chain inet ss_spec ss_spec_router
$NFT add rule inet ss_spec ss_spec_router ip daddr @ssr_gen_router return
$NFT add rule inet ss_spec ss_spec_router goto ss_spec_wan_fw
$NFT add chain inet ss_spec ss_spec_output { type nat hook output priority dstnat\; }
$NFT add rule inet ss_spec ss_spec_output tcp dport comment "\"$TAG\"" goto ss_spec_router
$NFT add chain inet ss_spec ss_spec_router 2>/dev/null
$NFT add rule inet ss_spec ss_spec_router ip daddr @ssr_gen_router return 2>/dev/null
$NFT add rule inet ss_spec ss_spec_router jump ss_spec_wan_fw 2>/dev/null
$NFT add chain inet ss_spec ss_spec_output '{ type nat hook output priority dstnat; }' 2>/dev/null
$NFT add rule inet ss_spec ss_spec_output tcp comment "\"$TAG\"" jump ss_spec_router 2>/dev/null
;;
esac
return 0
@@ -431,7 +447,7 @@ ac_rule_nft() {
ac_rule_iptables() {
if [ -n "$LAN_AC_IP" ]; then
case "${LAN_AC_IP:0:1}" in
case "${LAN_AC_IP%${LAN_AC_IP#?}}" in
w | W)
MATCH_SET="-m set --match-set ss_spec_lan_ac src"
;;
@@ -446,14 +462,14 @@ ac_rule_iptables() {
fi
ipset -! -R <<-EOF || return 1
create ss_spec_lan_ac hash:net
$(for ip in ${LAN_AC_IP:1}; do echo "add ss_spec_lan_ac $ip"; done)
$(for ip in ${LAN_AC_IP#?}; do echo "add ss_spec_lan_ac $ip"; done)
EOF
if [ -z "$Interface" ]; then
$IPT -I PREROUTING 1 -p tcp $EXT_ARGS $MATCH_SET -m comment --comment "$TAG" -j SS_SPEC_WAN_AC
else
for name in $Interface; do
local IFNAME=$(uci -P /var/state get network.$name.ifname 2>/dev/null)
[ -z "$IFNAME" ] && IFNAME=$(uci -P /var/state get network.$name.device 2>/dev/null)
local IFNAME=$(uci -P /var/state get network."$name".ifname 2>/dev/null)
[ -z "$IFNAME" ] && IFNAME=$(uci -P /var/state get network."$name".device 2>/dev/null)
[ -n "$IFNAME" ] && $IPT -I PREROUTING 1 ${IFNAME:+-i $IFNAME} -p tcp $EXT_ARGS $MATCH_SET -m comment --comment "$TAG" -j SS_SPEC_WAN_AC
done
fi
@@ -487,75 +503,85 @@ tp_rule() {
}
tp_rule_nft() {
# Set up routing for TPROXY
ip rule add fwmark 0x01/0x01 table 100
ip route add local 0.0.0.0/0 dev lo table 100
[ -n "$TPROXY" ] || return 0
# Create TPROXY chain in mangle table
# set up routing table for tproxy
ip rule add fwmark 0x01/0x01 table 100 2>/dev/null
ip route add local 0.0.0.0/0 dev lo table 100 2>/dev/null
# create mangle table and tproxy chain
$NFT add table ip ss_spec_mangle 2>/dev/null
$NFT add chain ip ss_spec_mangle ss_spec_tproxy { type filter hook prerouting priority mangle\; }
# use priority mangle for compatibility with other rules
$NFT add chain ip ss_spec_mangle ss_spec_tproxy '{ type filter hook prerouting priority mangle; }' 2>/dev/null
# Add basic return rules
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp dport 53 return
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp ip daddr 0.0.0.0/8 return
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp ip daddr 10.0.0.0/8 return
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp ip daddr 127.0.0.0/8 return
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp ip daddr 169.254.0.0/16 return
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp ip daddr 172.16.0.0/12 return
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp ip daddr 192.168.0.0/16 return
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp ip daddr 224.0.0.0/4 return
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp ip daddr 240.0.0.0/4 return
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp dport != 53 ip daddr $SERVER return
# basic return rules in tproxy chain
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp dport 53 return 2>/dev/null
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp ip daddr 0.0.0.0/8 return 2>/dev/null
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp ip daddr 10.0.0.0/8 return 2>/dev/null
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp ip daddr 127.0.0.0/8 return 2>/dev/null
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp ip daddr 169.254.0.0/16 return 2>/dev/null
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp ip daddr 172.16.0.0/12 return 2>/dev/null
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp ip daddr 192.168.0.0/16 return 2>/dev/null
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp ip daddr 224.0.0.0/4 return 2>/dev/null
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp ip daddr 240.0.0.0/4 return 2>/dev/null
# Handle different UDP server
# avoid redirecting to udp server address - 修正变量名
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp dport != 53 ip daddr "$server" return 2>/dev/null
# if server != SERVER add SERVER to whitelist set (so tproxy won't touch it)
if [ "$server" != "$SERVER" ]; then
$NFT add element inet ss_spec whitelist { $SERVER }
$NFT add element inet ss_spec whitelist "{ $SERVER }" 2>/dev/null
fi
# Access control rules
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp ip saddr @bplan return
# access control and tproxy rules
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp ip saddr @bplan return 2>/dev/null
if [ -n "$PROXY_PORTS" ]; then
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp $PROXY_PORTS ip saddr @fplan tproxy to :$LOCAL_PORT meta mark set 0x01
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp dport "$PROXY_PORTS" ip saddr @fplan tproxy to :"$LOCAL_PORT" meta mark set 0x01 2>/dev/null
else
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp ip saddr @fplan tproxy to :$LOCAL_PORT meta mark set 0x01
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp ip saddr @fplan tproxy to :"$LOCAL_PORT" meta mark set 0x01 2>/dev/null
fi
# Handle different run modes for nftables
case "$RUNMODE" in
router)
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp ip daddr @ss_spec_wan_ac return
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp ip daddr @china return
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp dport 80 drop
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp ip saddr @gmlan ip daddr != @china tproxy to :$LOCAL_PORT meta mark set 0x01
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp ip daddr @ss_spec_wan_ac return 2>/dev/null
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp ip daddr @china return 2>/dev/null
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp dport 80 drop 2>/dev/null
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp ip saddr @gmlan ip daddr != @china tproxy to :"$LOCAL_PORT" meta mark set 0x01 2>/dev/null
if [ -n "$PROXY_PORTS" ]; then
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp $PROXY_PORTS ip daddr != @ss_spec_wan_ac tproxy to :$LOCAL_PORT meta mark set 0x01
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp dport "$PROXY_PORTS" ip daddr != @ss_spec_wan_ac tproxy to :"$LOCAL_PORT" meta mark set 0x01 2>/dev/null
else
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp ip daddr != @ss_spec_wan_ac tproxy to :$LOCAL_PORT meta mark set 0x01
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp ip daddr != @ss_spec_wan_ac tproxy to :"$LOCAL_PORT" meta mark set 0x01 2>/dev/null
fi
;;
gfw)
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp ip daddr @china return
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp dport 80 drop
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp ip daddr @china return 2>/dev/null
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp dport 80 drop 2>/dev/null
if [ -n "$PROXY_PORTS" ]; then
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp $PROXY_PORTS ip daddr @gfwlist tproxy to :$LOCAL_PORT meta mark set 0x01
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp dport "$PROXY_PORTS" ip daddr @gfwlist tproxy to :"$LOCAL_PORT" meta mark set 0x01 2>/dev/null
fi
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp ip saddr @gmlan ip daddr != @china tproxy to :$LOCAL_PORT meta mark set 0x01
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp ip saddr @gmlan ip daddr != @china tproxy to :"$LOCAL_PORT" meta mark set 0x01 2>/dev/null
;;
oversea)
if [ -n "$PROXY_PORTS" ]; then
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp $PROXY_PORTS ip saddr @oversea tproxy to :$LOCAL_PORT meta mark set 0x01
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp $PROXY_PORTS ip daddr @china tproxy to :$LOCAL_PORT meta mark set 0x01
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp dport "$PROXY_PORTS" ip saddr @oversea tproxy to :"$LOCAL_PORT" meta mark set 0x01 2>/dev/null
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp dport "$PROXY_PORTS" ip daddr @china tproxy to :"$LOCAL_PORT" meta mark set 0x01 2>/dev/null
fi
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp ip saddr @gmlan tproxy to :$LOCAL_PORT meta mark set 0x01
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp ip saddr @gmlan tproxy to :"$LOCAL_PORT" meta mark set 0x01 2>/dev/null
;;
all)
if [ -n "$PROXY_PORTS" ]; then
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp $PROXY_PORTS tproxy to :$LOCAL_PORT meta mark set 0x01
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp dport "$PROXY_PORTS" tproxy to :"$LOCAL_PORT" meta mark set 0x01 2>/dev/null
else
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp tproxy to :$LOCAL_PORT meta mark set 0x01
$NFT add rule ip ss_spec_mangle ss_spec_tproxy udp tproxy to :"$LOCAL_PORT" meta mark set 0x01 2>/dev/null
fi
;;
esac
# insert jump from ip prerouting to our tproxy chain
$NFT add rule ip ss_spec_mangle prerouting udp comment "\"$TAG\"" jump ss_spec_tproxy 2>/dev/null
return 0
}
tp_rule_iptables() {
@@ -572,8 +598,8 @@ tp_rule_iptables() {
$ipt -A SS_SPEC_TPROXY -p udp -d 192.168.0.0/16 -j RETURN
$ipt -A SS_SPEC_TPROXY -p udp -d 224.0.0.0/4 -j RETURN
$ipt -A SS_SPEC_TPROXY -p udp -d 240.0.0.0/4 -j RETURN
$ipt -A SS_SPEC_TPROXY -p udp ! --dport 53 -d $SERVER -j RETURN
[ "$server" != "$SERVER" ] && ipset -! add whitelist $SERVER
$ipt -A SS_SPEC_TPROXY -p udp ! --dport 53 -d "$SERVER" -j RETURN
[ "$server" != "$SERVER" ] && ipset -! add whitelist "$SERVER"
$ipt -A SS_SPEC_TPROXY -p udp -m set --match-set bplan src -j RETURN
$ipt -A SS_SPEC_TPROXY -p udp $PROXY_PORTS -m set --match-set fplan src -j TPROXY --on-port "$LOCAL_PORT" --tproxy-mark 0x01/0x01
case "$RUNMODE" in
@@ -603,8 +629,8 @@ tp_rule_iptables() {
$ipt -I PREROUTING 1 -p udp $EXT_ARGS $MATCH_SET -m comment --comment "$TAG" -j SS_SPEC_TPROXY
else
for name in $Interface; do
local IFNAME=$(uci -P /var/state get network.$name.ifname 2>/dev/null)
[ -z "$IFNAME" ] && IFNAME=$(uci -P /var/state get network.$name.device 2>/dev/null)
local IFNAME=$(uci -P /var/state get network."$name".ifname 2>/dev/null)
[ -z "$IFNAME" ] && IFNAME=$(uci -P /var/state get network."$name".device 2>/dev/null)
[ -n "$IFNAME" ] && $ipt -I PREROUTING 1 ${IFNAME:+-i $IFNAME} -p udp $EXT_ARGS $MATCH_SET -m comment --comment "$TAG" -j SS_SPEC_TPROXY
done
fi
@@ -653,15 +679,17 @@ gen_include() {
gen_include_nft() {
# Generate nftables include file for firewall4
cat <<-EOF >>$FWI
[ -n "$FWI" ] && echo '#!/bin/sh' >"$FWI"
cat <<-'EOF' >>"$FWI"
# Clear existing ss_spec tables
nft delete table inet ss_spec 2>/dev/null
nft delete table ip ss_spec 2>/dev/null
nft delete table ip ss_spec_mangle 2>/dev/null
# Restore shadowsocks nftables rules
$(nft list ruleset | grep -A 1000 "table inet ss_spec\|table ip ss_spec")
nft list ruleset | awk '/table (inet|ip) ss_spec/{flag=1} flag'
EOF
chmod +x "$FWI"
}
gen_include_iptables() {
@@ -709,7 +737,7 @@ while getopts ":m:s:l:S:L:i:e:a:B:b:w:p:G:D:F:N:M:I:oOuUfgrczh" arg; do
LAN_BP_IP=$OPTARG
;;
b)
WAN_BP_IP=$(for ip in $OPTARG; do echo $ip; done)
WAN_BP_IP=$(for ip in $OPTARG; do echo "$ip"; done)
;;
w)
WAN_FW_IP=$OPTARG
@@ -767,10 +795,15 @@ while getopts ":m:s:l:S:L:i:e:a:B:b:w:p:G:D:F:N:M:I:oOuUfgrczh" arg; do
esac
done
if [ -z "$server" -o -z "$local_port" ]; then
if [ -z "$server" ] || [ -z "$local_port" ]; then
usage 2
fi
if ! echo "$local_port" | grep -qE '^[0-9]+$'; then
loger 3 "Invalid local port: $local_port"
exit 1
fi
case "$TPROXY" in
1)
SERVER=$server
@@ -782,7 +815,10 @@ case "$TPROXY" in
;;
esac
flush_r && fw_rule && ipset_r && ac_rule && tp_rule && gen_include
RET=$?
[ "$RET" = 0 ] || loger 3 "Start failed!"
exit $RET
if flush_r && fw_rule && ipset_r && ac_rule && tp_rule && gen_include; then
loger 5 "Rules applied successfully"
exit 0
else
loger 3 "Start failed!"
exit 1
fi

View File

@@ -331,8 +331,8 @@ end
mux = (server.v2ray_protocol ~= "wireguard") and {
-- mux
enabled = (server.mux == "1"), -- Mux
concurrency = (server.mux == "1" and (tonumber(server.concurrency) or -1)) or nil, -- TCP 最大并发
xudpConcurrency = (server.mux == "1" and (tonumber(server.xudpConcurrency) or 16)) or nil, -- UDP 最大并发
concurrency = (server.mux == "1" and (tonumber(server.concurrency) or -1)) or nil, -- TCP 最大并发连接数
xudpConcurrency = (server.mux == "1" and (tonumber(server.xudpConcurrency) or 16)) or nil, -- UDP 最大并发连接数
xudpProxyUDP443 = (server.mux == "1" and (server.xudpProxyUDP443 or "reject")) or nil -- 对被代理的 UDP/443 流量处理方式
} or nil
}
@@ -631,6 +631,8 @@ local tuic = {
return nil
end
end)() or nil,
ipstack_prefer = (server.tuic_dual_stack == "1") and server.ipstack_prefer or nil,
skip_cert_verify = (server.insecure == "1" or server.insecure == true or server.insecure == "true"),
disable_sni = (server.disable_sni == "1") and true or false,
zero_rtt_handshake = (server.zero_rtt_handshake == "1") and true or false,
send_window = tonumber(server.send_window),
@@ -715,3 +717,4 @@ function config:handleIndex(index)
end
local f = config:new()
f:handleIndex(server.type)

View File

@@ -27,7 +27,7 @@ config server_subscribe
option auto_update_day_time '2'
option auto_update_min_time '0'
option user_agent 'v2rayN/9.99'
option filter_words '过期时间/剩余流量/QQ群/官网/防失联地址/回国'
option filter_words '过期/套餐/剩余/QQ群/官网/防失联/回国'
config access_control
option lan_ac_mode '0'

View File

@@ -42,6 +42,7 @@ local v2_ss = luci.sys.exec('type -t -p ' .. ss_program .. ' 2>/dev/null') ~= ""
local has_ss_type = luci.sys.exec('type -t -p ' .. ss_program .. ' 2>/dev/null') ~= "" and ss_type
local v2_tj = luci.sys.exec('type -t -p trojan') ~= "" and "trojan" or "v2ray"
local hy2_type = luci.sys.exec('type -t -p hysteria') ~= "" and "hysteria2"
local tuic_type = luci.sys.exec('type -t -p tuic-client') ~= "" and "tuic"
local log = function(...)
print(os.date("%Y-%m-%d %H:%M:%S ") .. table.concat({...}, " "))
end
@@ -173,34 +174,6 @@ local function isCompleteJSON(str)
local success, _ = pcall(jsonParse, str)
return success
end
local function detectNodeType(rawContent)
-- 去掉 # 前后空格,处理 HTML 转义 &amp;
local content = trim(rawContent:gsub("&[a-zA-Z]+;", "&"):gsub("%s*#%s*", "#"))
-- 找到 # 分隔位置
local idx_sp = content:find("#") or 0
local info = content:sub(1, idx_sp > 0 and idx_sp - 1 or #content):gsub("/%?", "?")
-- 拆 base64 主体和 ? 参数部分
local uri_main, query_str = info:match("^([^?]+)%??(.*)$")
local params = {}
if query_str and query_str ~= "" then
for _, v in ipairs(split(query_str, '&')) do
local t = split(v, '=')
if #t >= 2 then
params[t[1]] = UrlDecode(t[2])
end
end
end
-- 判断是否是 Xray-SS 节点
if params["type"] then
return "shadowsocks"
else
return "ss"
end
end
-- 处理数据
local function processData(szType, content)
local result = {type = szType, local_port = 1234, kcp_param = '--nocomp'}
@@ -211,14 +184,6 @@ local function processData(szType, content)
end
end
-- 协议头识别
if szType == "ss" then
local nodeType = detectNodeType(content)
if nodeType == "shadowsocks" then
szType = "shadowsocks" -- 替换类型
end
end
if szType == "hysteria2" or szType == "hy2" then
local url = URL.parse("http://" .. content)
local params = url.query
@@ -261,7 +226,7 @@ local function processData(szType, content)
end
if params.alpn then
local alpn = {}
for v in params.alpn:gmatch("[^,]+") do
for v in params.alpn:gmatch("[^,;|%s]+") do
table.insert(alpn, v)
end
result.tls_alpn = alpn
@@ -353,8 +318,10 @@ local function processData(szType, content)
result.xhttp_host = info.host
result.xhttp_path = info.path
-- 检查 extra 参数是否存在且非空
result.enable_xhttp_extra = (info.extra and info.extra ~= "") and "1" or nil
result.xhttp_extra = (info.extra and info.extra ~= "") and info.extra or nil
if params.extra and params.extra ~= "" then
result.enable_xhttp_extra = "1"
result.xhttp_extra = params.extra
end
-- 尝试解析 JSON 数据
local success, Data = pcall(jsonParse, info.extra or "")
if success and type(Data) == "table" then
@@ -435,20 +402,21 @@ local function processData(szType, content)
result.security = info.security
end
elseif szType == "ss" then
local content = trim(content:gsub("&[a-zA-Z]+;", "&"):gsub("%s*#%s*", "#"))
local idx_sp = content:find("#") or 0
local alias = ""
if idx_sp > 0 then
alias = UrlDecode(content:sub(idx_sp + 1))
alias = content:sub(idx_sp + 1, -1)
content = content:sub(0, idx_sp - 1):gsub("/%?", "?")
end
local info = content:sub(1, idx_sp > 0 and idx_sp - 1 or #content):gsub("/%?", "?")
result.alias = UrlDecode(alias)
-- 拆 base64 主体和 ? 参数部分
local uri_main, query_str = info:match("^([^?]+)%??(.*)$")
--log("SS 节点格式:", uri_main)
local info = content
local find_index, query = info:match("^([^?]+)%??(.*)$")
--log("SS 节点格式:", find_index)
local params = {}
if query_str and query_str ~= "" then
for _, v in ipairs(split(query_str, '&')) do
if query and query ~= "" then
for _, v in ipairs(split(query, '&')) do
local t = split(v, '=')
if #t >= 2 then
params[t[1]] = UrlDecode(t[2])
@@ -456,28 +424,29 @@ local function processData(szType, content)
end
end
local is_old_format = uri_main:find("@") and not uri_main:find("://.*@")
local base64_str, host_port, userinfo, server, port, method, password
if not params.type or params.type == "" then
local is_old_format = find_index:find("@") and not find_index:find("://.*@")
local old_base64, host_port, userinfo, server, port, method, password
if is_old_format then
-- 旧格式base64(method:pass)@host:port
base64_str, host_port = uri_main:match("^([^@]+)@(.-)$")
log("SS 节点旧格式解析:", base64_str)
if not base64_str or not host_port then
log("SS 节点旧格式解析失败:", uri_main)
old_base64, host_port = find_index:match("^([^@]+)@(.-)$")
log("SS 节点旧格式解析:", old_base64)
if not old_base64 or not host_port then
log("SS 节点旧格式解析失败:", find_index)
return nil
end
local decoded = base64Decode(UrlDecode(base64_str))
local decoded = base64Decode(UrlDecode(old_base64))
if not decoded then
log("SS base64 解码失败(旧格式):", base64_str)
log("SS base64 解码失败(旧格式):", old_base64)
return nil
end
userinfo = decoded
else
-- 新格式base64(method:pass@host:port)
local decoded = base64Decode(UrlDecode(uri_main))
local decoded = base64Decode(UrlDecode(find_index))
if not decoded then
log("SS base64 解码失败(新格式):", uri_main)
log("SS base64 解码失败(新格式):", find_index)
return nil
end
userinfo, host_port = decoded:match("^(.-)@(.-)$")
@@ -488,13 +457,13 @@ local function processData(szType, content)
end
-- 解析加密方式和密码(允许密码包含冒号)
local split_pos = userinfo:find(":")
if not split_pos then
local meth_pass = userinfo:find(":")
if not meth_pass then
log("SS 用户信息格式错误:", userinfo)
return nil
end
method = userinfo:sub(1, split_pos - 1)
password = userinfo:sub(split_pos + 1)
method = userinfo:sub(1, meth_pass - 1)
password = userinfo:sub(meth_pass + 1)
-- 判断密码是否经过url编码
local function isURLEncodedPassword(pwd)
@@ -527,23 +496,13 @@ local function processData(szType, content)
end
-- 填充 result
result.alias = alias
result.type = v2_ss
result.v2ray_protocol = (v2_ss == "v2ray") and "shadowsocks" or nil
result.has_ss_type = has_ss_type
result.encrypt_method_ss = method
result.password = password
result.server = server
result.server_port = port
-- 仅在 v2ray + shadowsocks 协议时处理 ECH
if v2_ss == "v2ray" and result.v2ray_protocol == "shadowsocks" then
if params.ech and params.ech ~= "" then
result.enable_ech = "1"
result.ech_config = ech
end
end
-- 插件处理
if params.plugin then
local plugin_info = UrlDecode(params.plugin)
@@ -604,6 +563,113 @@ local function processData(szType, content)
-- log("不支持的SS加密方法:", method)
result.server = nil
end
else
local url = URL.parse("http://" .. info)
local params = url.query
v2_ss = "v2ray"
result.type = v2_ss
result.v2ray_protocol = "shadowsocks"
result.server = url.host
result.server_port = url.port
-- 判断 @ 前部分是否为 Base64
local is_base64 = base64Decode(UrlDecode(url.user))
if is_base64:find(":") then
-- 新格式method:password
result.encrypt_method_ss, result.password = is_base64:match("^(.-):(.*)$")
else
-- 旧格式UUID 直接作为密码
result.password = url.user
result.encrypt_method_ss = params.encryption or "none"
end
result.transport = params.type or "raw"
if result.transport == "tcp" then
result.transport = "raw"
end
if result.transport == "splithttp" then
result.transport = "xhttp"
end
result.tls = (params.security == "tls" or params.security == "xtls") and "1" or "0"
if params.alpn and params.alpn ~= "" then
local alpn = {}
for v in params.alpn:gmatch("[^,;|%s]+") do
table.insert(alpn, v)
end
result.tls_alpn = params.alpn
end
result.tls_host = params.sni
result.tls_flow = (params.security == "tls" or params.security == "reality") and params.flow or nil
result.fingerprint = params.fp
result.reality = (params.security == "reality") and "1" or "0"
result.reality_publickey = params.pbk and UrlDecode(params.pbk) or nil
result.reality_shortid = params.sid
result.reality_spiderx = params.spx and UrlDecode(params.spx) or nil
-- 检查 ech 参数是否存在且非空
if params.ech and params.ech ~= "" then
result.enable_ech = "1"
result.ech_config = params.ech
end
-- 检查 pqv 参数是否存在且非空
if params.pqv and params.pqv ~= "" then
result.enable_mldsa65verify = "1"
result.reality_mldsa65verify = params.pqv
end
if result.transport == "ws" then
result.ws_host = (result.tls ~= "1") and (params.host and UrlDecode(params.host)) or nil
result.ws_path = params.path and UrlDecode(params.path) or "/"
elseif result.transport == "httpupgrade" then
result.httpupgrade_host = (result.tls ~= "1") and (params.host and UrlDecode(params.host)) or nil
result.httpupgrade_path = params.path and UrlDecode(params.path) or "/"
elseif result.transport == "xhttp" or result.transport == "splithttp" then
result.xhttp_host = (result.tls ~= "1") and (params.host and UrlDecode(params.host)) or nil
result.xhttp_mode = params.mode or "auto"
result.xhttp_path = params.path and UrlDecode(params.path) or "/"
-- 检查 extra 参数是否存在且非空
if params.extra and params.extra ~= "" then
result.enable_xhttp_extra = "1"
result.xhttp_extra = params.extra
end
-- 尝试解析 JSON 数据
local success, Data = pcall(jsonParse, params.extra or "")
if success and type(Data) == "table" then
local address = (Data.extra and Data.extra.downloadSettings and Data.extra.downloadSettings.address)
or (Data.downloadSettings and Data.downloadSettings.address)
result.download_address = address and address ~= "" and address or nil
else
-- 如果解析失败,清空下载地址
result.download_address = nil
end
-- make it compatible with bullshit, "h2" transport is non-existent at all
elseif result.transport == "http" or result.transport == "h2" then
result.transport = "h2"
result.h2_host = params.host and UrlDecode(params.host) or nil
result.h2_path = params.path and UrlDecode(params.path) or nil
elseif result.transport == "kcp" then
result.kcp_guise = params.headerType or "none"
result.seed = params.seed
result.mtu = 1350
result.tti = 50
result.uplink_capacity = 5
result.downlink_capacity = 20
result.read_buffer_size = 2
result.write_buffer_size = 2
elseif result.transport == "quic" then
result.quic_guise = params.headerType or "none"
result.quic_security = params.quicSecurity or "none"
result.quic_key = params.key
elseif result.transport == "grpc" then
result.serviceName = params.serviceName
result.grpc_mode = params.mode or "gun"
elseif result.transport == "tcp" or result.transport == "raw" then
result.tcp_guise = params.headerType or "none"
if result.tcp_guise == "http" then
result.tcp_host = params.host and UrlDecode(params.host) or nil
result.tcp_path = params.path and UrlDecode(params.path) or nil
end
end
end
elseif szType == "sip008" then
result.type = v2_ss
result.v2ray_protocol = (v2_ss == "v2ray") and "shadowsocks" or nil
@@ -637,87 +703,82 @@ local function processData(szType, content)
result.server = nil
end
elseif szType == "trojan" then
local params = {}
local idx_sp = 0
local alias = ""
-- 提取别名(如果存在)
local alias = ""
if content:find("#") then
idx_sp = content:find("#")
local idx_sp = content:find("#")
alias = content:sub(idx_sp + 1, -1)
content = content:sub(0, idx_sp - 1)
end
local info = content:sub(1, idx_sp > 0 and idx_sp - 1 or #content)
local hostInfo = split(info, "@")
-- 基础验证
if #hostInfo < 2 then
--log("Trojan节点格式错误: 缺少@符号")
return nil
end
local userinfo = hostInfo[1]
local hostPort = hostInfo[2]
-- 分离服务器地址和端口
local hostParts = split(hostPort, ":")
local server = hostParts[1]
local port = hostParts[2]
-- 验证服务器地址和端口
if #hostParts < 2 then
--log("Trojan节点格式错误: 缺少端口号")
return nil
end
result.alias = UrlDecode(alias)
result.type = v2_tj
result.v2ray_protocol = "trojan"
result.server = server
result.password = userinfo
-- 分离和提取 password
local Info = content
local params = {}
if Info:find("@") then
local contents = split(Info, "@")
result.password = UrlDecode(contents[1])
local port = "443"
Info = (contents[2] or ""):gsub("/%?", "?")
-- 分离主机和 query 参数key=value&key2=value2
local query = split(Info, "%?")
local host_port = query[1]
for _, v in pairs(split(query[2], '&')) do
local t = split(v, '=')
if #t > 1 then
params[string.lower(t[1])] = UrlDecode(t[2])
end
end
-- 提取服务器地址和端口
if host_port:find(":") then
local sp = split(host_port, ":")
result.server_port = sp[#sp]
result.server = sp[1]
else
result.server = host_port
end
-- 默认设置
-- 按照官方的建议 默认验证ssl证书
result.insecure = "0"
result.tls = "1"
-- 解析查询参数(如果存在)
if port:find("?") then
local queryParts = split(port, "?")
result.server_port = queryParts[1]
-- 解析查询参数
for _, v in pairs(split(queryParts[2], '&')) do
local t = split(v, '=')
if #t >= 2 then
params[t[1]] = t[2]
end
end
-- 处理参数
if params.alpn then
-- 处理 alpn 参数
result.tls_alpn = params.alpn
end
if params.sni then
if params.peer or params.sni then
-- 未指定peersni默认使用remote addr
result.tls_host = params.sni
result.tls_host = params.peer or params.sni
end
if params.allowInsecure then
-- 处理 insecure 参数
if params.allowinsecure == "1" or params.allowinsecure == "0" then
result.insecure = params.allowInsecure
else
result.insecure = string.lower(params.allowinsecure) == "true" and "1" or "0"
end
end
if params.tfo then
-- 处理 fast open 参数
result.fast_open = params.tfo
end
else
result.server_port = port
end
-- 如果 Tojan 程序未安装则跳过订阅
if not v2_tj then
if not v2_tj or v2_tj == "" then
return nil
end
if params.type and params.type ~= "" then
v2_tj = "v2ray"
result.type = v2_tj
result.v2ray_protocol = "trojan"
if v2_tj ~= "trojan" then
if params.fp then
-- 处理 fingerprint 参数
@@ -747,8 +808,10 @@ local function processData(szType, content)
result.xhttp_mode = params.mode or "auto"
result.xhttp_path = params.path and UrlDecode(params.path) or "/"
-- 检查 extra 参数是否存在且非空
result.enable_xhttp_extra = (params.extra and params.extra ~= "") and "1" or nil
result.xhttp_extra = (params.extra and params.extra ~= "") and params.extra or nil
if params.extra and params.extra ~= "" then
result.enable_xhttp_extra = "1"
result.xhttp_extra = params.extra
end
-- 尝试解析 JSON 数据
local success, Data = pcall(jsonParse, params.extra or "")
if success and type(Data) == "table" then
@@ -786,6 +849,9 @@ local function processData(szType, content)
result.tcp_path = params.path and UrlDecode(params.path) or nil
end
end
else
result.type = v2_tj
end
end
elseif szType == "vless" then
local url = URL.parse("http://" .. content)
@@ -798,62 +864,85 @@ local function processData(szType, content)
result.server_port = url.port
result.vmess_id = url.user
result.vless_encryption = params.encryption or "none"
-- 处理传输类型
result.transport = params.type or "raw"
if result.transport == "tcp" then
result.transport = "raw"
end
if result.transport == "splithttp" then
elseif result.transport == "splithttp" then
result.transport = "xhttp"
elseif result.transport == "http" then
result.transport = "h2"
end
result.tls = (params.security == "tls" or params.security == "xtls") and "1" or "0"
-- TLS / Reality 标志
local security = params.security or ""
result.tls = (security == "tls" or security == "xtls") and "1" or "0"
result.reality = (security == "reality") and "1" or "0"
-- 统一 TLS / Reality 公共字段
result.tls_host = params.sni
result.fingerprint = params.fp
result.tls_flow = (security == "tls" or security == "reality") and params.flow or nil
-- 处理 alpn 列表
if params.alpn and params.alpn ~= "" then
local alpn = {}
for v in params.alpn:gmatch("[^,]+") do
for v in params.alpn:gmatch("[^,;|%s]+") do
table.insert(alpn, v)
end
result.tls_alpn = alpn
end
result.tls_host = params.sni
result.tls_flow = (params.security == "tls" or params.security == "reality") and params.flow or nil
result.fingerprint = params.fp
result.reality = (params.security == "reality") and "1" or "0"
-- Reality 参数
if security == "reality" then
result.reality_publickey = params.pbk and UrlDecode(params.pbk) or nil
result.reality_shortid = params.sid
result.reality_spiderx = params.spx and UrlDecode(params.spx) or nil
-- 检查 ech 参数是否存在且非空
result.enable_ech = (params.ech and params.ech ~= "") and "1" or nil
result.ech_config = (params.ech and params.ech ~= "") and params.ech or nil
-- 检查 pqv 参数是否存在且非空
result.enable_mldsa65verify = (params.pqv and params.pqv ~= "") and "1" or nil
result.reality_mldsa65verify = (params.pqv and params.pqv ~= "") and params.pqv or nil
-- PQ 验证参数
if params.pqv and params.pqv ~= "" then
result.enable_mldsa65verify = "1"
result.reality_mldsa65verify = params.pqv
end
end
-- ECH 参数TLS 才有)
if security == "tls" and params.ech and params.ech ~= "" then
result.enable_ech = "1"
result.ech_config = params.ech
end
-- 各种传输类型
if result.transport == "ws" then
result.ws_host = (result.tls ~= "1") and (params.host and UrlDecode(params.host)) or nil
result.ws_host = (result.tls ~= "1" and result.reality ~= "1") and (params.host and UrlDecode(params.host)) or nil
result.ws_path = params.path and UrlDecode(params.path) or "/"
elseif result.transport == "httpupgrade" then
result.httpupgrade_host = (result.tls ~= "1") and (params.host and UrlDecode(params.host)) or nil
result.httpupgrade_host = (result.tls ~= "1" and result.reality ~= "1") and (params.host and UrlDecode(params.host)) or nil
result.httpupgrade_path = params.path and UrlDecode(params.path) or "/"
elseif result.transport == "xhttp" or result.transport == "splithttp" then
result.xhttp_host = (result.tls ~= "1") and (params.host and UrlDecode(params.host)) or nil
elseif result.transport == "xhttp" then
result.xhttp_host = (result.tls ~= "1" and result.reality ~= "1") and (params.host and UrlDecode(params.host)) or nil
result.xhttp_mode = params.mode or "auto"
result.xhttp_path = params.path and UrlDecode(params.path) or "/"
-- 检查 extra 参数是否存在且非空
result.enable_xhttp_extra = (params.extra and params.extra ~= "") and "1" or nil
result.xhttp_extra = (params.extra and params.extra ~= "") and params.extra or nil
-- 尝试解析 JSON 数据
if params.extra and params.extra ~= "" then
result.enable_xhttp_extra = "1"
result.xhttp_extra = params.extra
end
local success, Data = pcall(jsonParse, params.extra or "")
if success and type(Data) == "table" then
local address = (Data.extra and Data.extra.downloadSettings and Data.extra.downloadSettings.address)
or (Data.downloadSettings and Data.downloadSettings.address)
result.download_address = address and address ~= "" and address or nil
else
-- 如果解析失败,清空下载地址
result.download_address = nil
end
-- make it compatible with bullshit, "h2" transport is non-existent at all
elseif result.transport == "http" or result.transport == "h2" then
result.transport = "h2"
elseif result.transport == "h2" then
result.h2_host = params.host and UrlDecode(params.host) or nil
result.h2_path = params.path and UrlDecode(params.path) or nil
elseif result.transport == "kcp" then
result.kcp_guise = params.headerType or "none"
result.seed = params.seed
@@ -863,125 +952,123 @@ local function processData(szType, content)
result.downlink_capacity = 20
result.read_buffer_size = 2
result.write_buffer_size = 2
elseif result.transport == "quic" then
result.quic_guise = params.headerType or "none"
result.quic_security = params.quicSecurity or "none"
result.quic_key = params.key
elseif result.transport == "grpc" then
result.serviceName = params.serviceName
result.grpc_mode = params.mode or "gun"
elseif result.transport == "tcp" or result.transport == "raw" then
elseif result.transport == "raw" then
result.tcp_guise = params.headerType or "none"
if result.tcp_guise == "http" then
result.tcp_host = params.host and UrlDecode(params.host) or nil
result.tcp_path = params.path and UrlDecode(params.path) or nil
end
end
elseif szType == "shadowsocks" then
local content = trim(content:gsub("&[a-zA-Z]+;", "&"):gsub("%s*#%s*", "#"))
local idx_sp = content:find("#") or 0
elseif szType == "tuic" then
-- 提取别名(如果存在)
local alias = ""
if idx_sp > 0 then
alias = UrlDecode(content:sub(idx_sp + 1))
if content:find("#") then
local idx_sp = content:find("#")
alias = content:sub(idx_sp + 1, -1)
content = content:sub(0, idx_sp - 1)
end
local info = content:sub(1, idx_sp > 0 and idx_sp - 1 or #content)
local url = URL.parse("http://" .. info)
local params = url.query
result.alias = UrlDecode(alias)
result.alias = alias
result.type = "v2ray"
result.v2ray_protocol = "shadowsocks"
result.server = url.host
result.server_port = url.port
-- 分离和提取 uuid 和 password
local Info = content
if Info:find("@") then
local contents = split(Info, "@")
if contents[1]:find(":") then
local userinfo = split(contents[1], ":")
result.tuic_uuid = UrlDecode(userinfo[1])
result.tuic_passwd = UrlDecode(userinfo[2])
end
Info = (contents[2] or ""):gsub("/%?", "?")
end
-- 判断 @ 前部分是否为 Base64
local is_base64_decoded = base64Decode(UrlDecode(url.user))
if is_base64_decoded:find(":") then
-- 新格式method:password
result.encrypt_method_ss, result.password = is_base64_decoded:match("^(.-):(.*)$")
-- 分离主机和 query 参数key=value&key2=value2
local query = split(Info, "%?")
local host_port = query[1]
local params = {}
for _, v in pairs(split(query[2], '&')) do
local t = split(v, '=')
if #t > 1 then
params[string.lower(t[1])] = UrlDecode(t[2])
end
end
-- 提取服务器地址和端口
if host_port:find(":") then
local sp = split(host_port, ":")
result.server_port = sp[#sp]
result.server = sp[1]
else
-- 旧格式UUID 直接作为密码
result.password = url.user
result.encrypt_method_ss = params.encryption or "none"
result.server = host_port
end
result.transport = params.type or "raw"
if result.transport == "tcp" then
result.transport = "raw"
end
if result.transport == "splithttp" then
result.transport = "xhttp"
end
result.tls = (params.security == "tls" or params.security == "xtls") and "1" or "0"
result.type = tuic_type
result.tuic_ip = params.ip or ""
result.udp_relay_mode = params.udp_relay_mode or "native"
result.congestion_control = params.congestion_control or "cubic"
result.heartbeat = params.heartbeat or "3"
result.timeout = params.timeout or "8"
result.gc_interval = params.gc_interval or "3"
result.gc_lifetime = params.gc_lifetime or "15"
result.send_window = params.send_window or "20971520"
result.receive_window = params.receive_window or "10485760"
result.tuic_max_package_size = params.max_packet_size or "1500"
-- alpn 支持逗号或分号分隔
if params.alpn and params.alpn ~= "" then
local alpn = {}
for v in params.alpn:gmatch("[^,]+") do
for v in params.alpn:gmatch("[^,;|%s]+") do
table.insert(alpn, v)
end
result.tls_alpn = alpn
result.tuic_alpn = alpn
end
result.tls_host = params.sni
result.tls_flow = (params.security == "tls" or params.security == "reality") and params.flow or nil
result.fingerprint = params.fp
result.reality = (params.security == "reality") and "1" or "0"
result.reality_publickey = params.pbk and UrlDecode(params.pbk) or nil
result.reality_shortid = params.sid
result.reality_spiderx = params.spx and UrlDecode(params.spx) or nil
-- 检查 ech 参数是否存在且非空
result.enable_ech = (params.ech and params.ech ~= "") and "1" or nil
result.ech_config = (params.ech and params.ech ~= "") and params.ech or nil
-- 检查 pqv 参数是否存在且非空
result.enable_mldsa65verify = (params.pqv and params.pqv ~= "") and "1" or nil
result.reality_mldsa65verify = (params.pqv and params.pqv ~= "") and params.pqv or nil
if result.transport == "ws" then
result.ws_host = (result.tls ~= "1") and (params.host and UrlDecode(params.host)) or nil
result.ws_path = params.path and UrlDecode(params.path) or "/"
elseif result.transport == "httpupgrade" then
result.httpupgrade_host = (result.tls ~= "1") and (params.host and UrlDecode(params.host)) or nil
result.httpupgrade_path = params.path and UrlDecode(params.path) or "/"
elseif result.transport == "xhttp" or result.transport == "splithttp" then
result.xhttp_host = (result.tls ~= "1") and (params.host and UrlDecode(params.host)) or nil
result.xhttp_mode = params.mode or "auto"
result.xhttp_path = params.path and UrlDecode(params.path) or "/"
-- 检查 extra 参数是否存在且非空
result.enable_xhttp_extra = (params.extra and params.extra ~= "") and "1" or nil
result.xhttp_extra = (params.extra and params.extra ~= "") and params.extra or nil
-- 尝试解析 JSON 数据
local success, Data = pcall(jsonParse, params.extra or "")
if success and type(Data) == "table" then
local address = (Data.extra and Data.extra.downloadSettings and Data.extra.downloadSettings.address)
or (Data.downloadSettings and Data.downloadSettings.address)
result.download_address = address and address ~= "" and address or nil
-- 处理 disable_sni 参数
if params.disable_sni then
if params.disable_sni == "1" or params.disable_sni == "0" then
result.disable_sni = params.disable_sni
else
-- 如果解析失败,清空下载地址
result.download_address = nil
result.disable_sni = string.lower(params.disable_sni) == "true" and "1" or "0"
end
-- make it compatible with bullshit, "h2" transport is non-existent at all
elseif result.transport == "http" or result.transport == "h2" then
result.transport = "h2"
result.h2_host = params.host and UrlDecode(params.host) or nil
result.h2_path = params.path and UrlDecode(params.path) or nil
elseif result.transport == "kcp" then
result.kcp_guise = params.headerType or "none"
result.seed = params.seed
result.mtu = 1350
result.tti = 50
result.uplink_capacity = 5
result.downlink_capacity = 20
result.read_buffer_size = 2
result.write_buffer_size = 2
elseif result.transport == "quic" then
result.quic_guise = params.headerType or "none"
result.quic_security = params.quicSecurity or "none"
result.quic_key = params.key
elseif result.transport == "grpc" then
result.serviceName = params.serviceName
result.grpc_mode = params.mode or "gun"
elseif result.transport == "tcp" or result.transport == "raw" then
result.tcp_guise = params.headerType or "none"
if result.tcp_guise == "http" then
result.tcp_host = params.host and UrlDecode(params.host) or nil
result.tcp_path = params.path and UrlDecode(params.path) or nil
end
-- 处理 zero_rtt_handshake 参数
if params.zero_rtt_handshake then
if params.zero_rtt_handshake == "1" or params.zero_rtt_handshake == "0" then
result.zero_rtt_handshake = params.zero_rtt_handshake
else
result.zero_rtt_handshake = string.lower(params.zero_rtt_handshake) == "true" and "1" or "0"
end
end
-- 处理 dual_stack 参数
if params.dual_stack then
if params.dual_stack == "1" or params.dual_stack == "0" then
result.dual_stack = params.dual_stack
else
result.dual_stack = string.lower(params.dual_stack) == "true" and "1" or "0"
end
-- 处理 ipstack_prefer 参数
if params.ipstack_prefer and params.ipstack_prefer ~= "" then
result.ipstack_prefer = params.ipstack_prefer
end
end
-- 处理 insecure 参数
if params.allowInsecure then
if params.allowinsecure == "1" or params.allowinsecure == "0" then
result.insecure = params.allowInsecure
else
result.insecure = string.lower(params.allowinsecure) == "true" and "1" or "0"
end
end
end
@@ -997,7 +1084,7 @@ local function processData(szType, content)
result.alias = nil
local switch_enable = result.switch_enable
result.switch_enable = nil
result.hashkey = md5(jsonStringify(result))
result.hashkey = md5(jsonStringify(result) .. "_" .. (alias or ""))
result.alias = alias
result.switch_enable = switch_enable
return result
@@ -1181,22 +1268,25 @@ local execute = function()
-- 其他 base64 格式
else
-- ssd 外的格式
nodes = split(base64Decode(raw):gsub(" ", "_"), "\n")
nodes = split(base64Decode(raw):gsub("\r\n", "\n"), "\n")
end
for _, v in ipairs(nodes) do
if v then
if v and not string.match(v, "^%s*$") then
xpcall(function()
local result
if szType then
result = processData(szType, v)
elseif not szType then
local node = trim(v)
local dat = split(node, "://")
-- 一些奇葩的链接用"&amp;"、"&lt;"当做"&""#"前后带空格
local link = node:gsub("&[a-zA-Z]+;", "&"):gsub("%s*#%s*", "#")
local dat = split(link, "://")
if dat and dat[1] and dat[2] then
local dat3 = ""
if dat[3] then
dat3 = "://" .. dat[3]
end
if dat[1] == 'ss' or dat[1] == 'trojan' then
if dat[1] == 'ss' or dat[1] == 'trojan' or dat[1] == 'tuic' then
result = processData(dat[1], dat[2] .. dat3)
else
result = processData(dat[1], base64Decode(dat[2]))
@@ -1209,6 +1299,7 @@ local execute = function()
if result then
-- 中文做地址的 也没有人拿中文域名搞就算中文域也有Puny Code SB 机场
if not result.server or not result.server_port
or result.server == "127.0.0.1"
or result.alias == "NULL"
or check_filer(result)
or result.server:match("[^0-9a-zA-Z%-_%.%s]")
@@ -1222,6 +1313,9 @@ local execute = function()
cache[groupHash][result.hashkey] = nodeResult[index][#nodeResult[index]]
end
end
end, function(err)
log(string.format("解析节点出错: %s\n原始数据: %s", tostring(err), tostring(v)))
end)
end
end
log('成功解析节点数量: ' .. #nodes)
@@ -1304,7 +1398,7 @@ local execute = function()
luci.sys.call("/etc/init.d/" .. name .. " stop > /dev/null 2>&1 &")
end
end
log('新增节点数量: ' .. add, '删除节点数量: ' .. del)
log('新增节点数量: ' .. add .. ', 删除节点数量: ' .. del)
log('订阅更新成功')
end
end