mirror of
https://github.com/itdoginfo/podkop.git
synced 2025-12-06 11:36:50 +03:00
@@ -21,11 +21,38 @@ return view.extend({
|
|||||||
o.value('proxy', ('Proxy'));
|
o.value('proxy', ('Proxy'));
|
||||||
o.ucisection = 'main';
|
o.ucisection = 'main';
|
||||||
|
|
||||||
o = s.taboption('basic', form.TextValue, 'proxy_string', _('Proxy Configuration URL'), _('Enter connection string starting with vless:// or ss:// for proxy configuration'));
|
o = s.taboption('basic', form.ListValue, 'proxy_config_type', _('Configuration Type'), _('Select how to configure the proxy'));
|
||||||
|
o.value('url', _('Connection URL'));
|
||||||
|
o.value('outbound', _('Outbound Config'));
|
||||||
|
o.default = 'url';
|
||||||
o.depends('mode', 'proxy');
|
o.depends('mode', 'proxy');
|
||||||
|
o.ucisection = 'main';
|
||||||
|
|
||||||
|
o = s.taboption('basic', form.TextValue, 'proxy_string', _('Proxy Configuration URL'), _('Enter connection string starting with vless:// or ss:// for proxy configuration'));
|
||||||
|
o.depends('proxy_config_type', 'url');
|
||||||
o.rows = 5;
|
o.rows = 5;
|
||||||
o.ucisection = 'main';
|
o.ucisection = 'main';
|
||||||
|
|
||||||
|
o = s.taboption('basic', form.TextValue, 'outbound_json', _('Outbound Configuration'), _('Enter complete outbound configuration in JSON format'));
|
||||||
|
o.depends('proxy_config_type', 'outbound');
|
||||||
|
o.rows = 10;
|
||||||
|
o.ucisection = 'main';
|
||||||
|
o.validate = function (section_id, value) {
|
||||||
|
if (!value || value.length === 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(value);
|
||||||
|
if (!parsed.type || !parsed.server || !parsed.server_port) {
|
||||||
|
return _('JSON must contain at least type, server and server_port fields');
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
return _('Invalid JSON format');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
o = s.taboption('basic', form.ListValue, 'interface', _('Network Interface'), _('Select network interface for VPN connection'));
|
o = s.taboption('basic', form.ListValue, 'interface', _('Network Interface'), _('Select network interface for VPN connection'));
|
||||||
o.depends('mode', 'vpn');
|
o.depends('mode', 'vpn');
|
||||||
o.ucisection = 'main';
|
o.ucisection = 'main';
|
||||||
@@ -88,14 +115,17 @@ return view.extend({
|
|||||||
o.rmempty = false;
|
o.rmempty = false;
|
||||||
o.ucisection = 'main';
|
o.ucisection = 'main';
|
||||||
|
|
||||||
o = s.taboption('basic', form.Flag, 'custom_domains_list_enabled', _('User Domain List'), _('Enable and manage your custom list of domains for selective routing'));
|
o = s.taboption('basic', form.ListValue, 'custom_domains_list_enabled', _('User Domain List Type'), _('Select how to add your custom domains'));
|
||||||
o.default = '0';
|
o.value('disabled', _('Disabled'));
|
||||||
|
o.value('dynamic', _('Dynamic List'));
|
||||||
|
o.value('text', _('Text List'));
|
||||||
|
o.default = 'disabled';
|
||||||
o.rmempty = false;
|
o.rmempty = false;
|
||||||
o.ucisection = 'main';
|
o.ucisection = 'main';
|
||||||
|
|
||||||
o = s.taboption('basic', form.DynamicList, 'custom_domains', _('User Domains'), _('Enter domain names without protocols (example: sub.example.com or example.com)'));
|
o = s.taboption('basic', form.DynamicList, 'custom_domains', _('User Domains'), _('Enter domain names without protocols (example: sub.example.com or example.com)'));
|
||||||
o.placeholder = 'Domains list';
|
o.placeholder = 'Domains list';
|
||||||
o.depends('custom_domains_list_enabled', '1');
|
o.depends('custom_domains_list_enabled', 'dynamic');
|
||||||
o.rmempty = false;
|
o.rmempty = false;
|
||||||
o.ucisection = 'main';
|
o.ucisection = 'main';
|
||||||
o.validate = function (section_id, value) {
|
o.validate = function (section_id, value) {
|
||||||
@@ -111,6 +141,31 @@ return view.extend({
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
o = s.taboption('basic', form.TextValue, 'custom_domains_text', _('User Domains List'), _('Enter domain names separated by comma, space or newline (example: sub.example.com, example.com or one domain per line)'));
|
||||||
|
o.placeholder = 'example.com, sub.example.com\ndomain.com test.com\nsubdomain.domain.com another.com, third.com';
|
||||||
|
o.depends('custom_domains_list_enabled', 'text');
|
||||||
|
o.rows = 10;
|
||||||
|
o.rmempty = false;
|
||||||
|
o.ucisection = 'main';
|
||||||
|
o.validate = function (section_id, value) {
|
||||||
|
if (!value || value.length === 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const domains = value.split(/[,\s\n]/)
|
||||||
|
.map(d => d.trim())
|
||||||
|
.filter(d => d.length > 0);
|
||||||
|
|
||||||
|
const domainRegex = /^(?!-)[A-Za-z0-9-]+([-.][A-Za-z0-9-]+)*\.[A-Za-z]{2,}$/;
|
||||||
|
|
||||||
|
for (const domain of domains) {
|
||||||
|
if (!domainRegex.test(domain)) {
|
||||||
|
return _('Invalid domain format: ' + domain + '. Enter domain without protocol');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
o = s.taboption('basic', form.Flag, 'custom_download_domains_list_enabled', _('Remote Domain Lists'), _('Download and use domain lists from remote URLs'));
|
o = s.taboption('basic', form.Flag, 'custom_download_domains_list_enabled', _('Remote Domain Lists'), _('Download and use domain lists from remote URLs'));
|
||||||
o.default = '0';
|
o.default = '0';
|
||||||
o.rmempty = false;
|
o.rmempty = false;
|
||||||
@@ -137,14 +192,18 @@ return view.extend({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
o = s.taboption('basic', form.Flag, 'custom_subnets_list_enabled', _('User Subnet List'), _('Enable and manage your custom list of IP subnets for selective routing'));
|
|
||||||
o.default = '0';
|
o = s.taboption('basic', form.ListValue, 'custom_subnets_list_enabled', _('User Subnet List Type'), _('Select how to add your custom subnets'));
|
||||||
|
o.value('disabled', _('Disabled'));
|
||||||
|
o.value('dynamic', _('Dynamic List'));
|
||||||
|
o.value('text', _('Text List (comma/space/newline separated)'));
|
||||||
|
o.default = 'disabled';
|
||||||
o.rmempty = false;
|
o.rmempty = false;
|
||||||
o.ucisection = 'main';
|
o.ucisection = 'main';
|
||||||
|
|
||||||
o = s.taboption('basic', form.DynamicList, 'custom_subnets', _('User Subnets'), _('Enter subnet in CIDR notation (example: 103.21.244.0/22)'));
|
o = s.taboption('basic', form.DynamicList, 'custom_subnets', _('User Subnets'), _('Enter subnets in CIDR notation (example: 103.21.244.0/22) or single IP addresses'));
|
||||||
o.placeholder = 'Subnets list';
|
o.placeholder = 'IP or subnet';
|
||||||
o.depends('custom_subnets_list_enabled', '1');
|
o.depends('custom_subnets_list_enabled', 'dynamic');
|
||||||
o.rmempty = false;
|
o.rmempty = false;
|
||||||
o.ucisection = 'main';
|
o.ucisection = 'main';
|
||||||
o.validate = function (section_id, value) {
|
o.validate = function (section_id, value) {
|
||||||
@@ -152,15 +211,15 @@ return view.extend({
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const subnetRegex = /^(\d{1,3}\.){3}\d{1,3}\/\d{1,2}$/;
|
const subnetRegex = /^(\d{1,3}\.){3}\d{1,3}(\/\d{1,2})?$/;
|
||||||
|
|
||||||
if (!subnetRegex.test(value)) {
|
if (!subnetRegex.test(value)) {
|
||||||
return _('Invalid subnet format. Use format: X.X.X.X/Y (like 103.21.244.0/22)');
|
return _('Invalid format. Use format: X.X.X.X or X.X.X.X/Y');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Разбираем IP и маску
|
||||||
const [ip, cidr] = value.split('/');
|
const [ip, cidr] = value.split('/');
|
||||||
const ipParts = ip.split('.');
|
const ipParts = ip.split('.');
|
||||||
const cidrNum = parseInt(cidr);
|
|
||||||
|
|
||||||
for (const part of ipParts) {
|
for (const part of ipParts) {
|
||||||
const num = parseInt(part);
|
const num = parseInt(part);
|
||||||
@@ -169,13 +228,59 @@ return view.extend({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cidrNum < 0 || cidrNum > 32) {
|
if (cidr !== undefined) {
|
||||||
return _('CIDR must be between 0 and 32');
|
const cidrNum = parseInt(cidr);
|
||||||
|
if (cidrNum < 0 || cidrNum > 32) {
|
||||||
|
return _('CIDR must be between 0 and 32');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
o = s.taboption('basic', form.TextValue, 'custom_subnets_text', _('User Subnets List'), _('Enter subnets in CIDR notation or single IP addresses, separated by comma, space or newline'));
|
||||||
|
o.placeholder = '103.21.244.0/22\n8.8.8.8\n1.1.1.1/32, 9.9.9.9 10.10.10.10';
|
||||||
|
o.depends('custom_subnets_list_enabled', 'text');
|
||||||
|
o.rows = 10;
|
||||||
|
o.rmempty = false;
|
||||||
|
o.ucisection = 'main';
|
||||||
|
o.validate = function (section_id, value) {
|
||||||
|
if (!value || value.length === 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Split by commas, spaces and newlines
|
||||||
|
const subnets = value.split(/[,\s\n]/)
|
||||||
|
.map(s => s.trim())
|
||||||
|
.filter(s => s.length > 0);
|
||||||
|
|
||||||
|
const subnetRegex = /^(\d{1,3}\.){3}\d{1,3}(\/\d{1,2})?$/;
|
||||||
|
|
||||||
|
for (const subnet of subnets) {
|
||||||
|
if (!subnetRegex.test(subnet)) {
|
||||||
|
return _('Invalid format: ' + subnet + '. Use format: X.X.X.X or X.X.X.X/Y');
|
||||||
|
}
|
||||||
|
|
||||||
|
const [ip, cidr] = subnet.split('/');
|
||||||
|
const ipParts = ip.split('.');
|
||||||
|
|
||||||
|
for (const part of ipParts) {
|
||||||
|
const num = parseInt(part);
|
||||||
|
if (num < 0 || num > 255) {
|
||||||
|
return _('IP parts must be between 0 and 255 in: ' + subnet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cidr !== undefined) {
|
||||||
|
const cidrNum = parseInt(cidr);
|
||||||
|
if (cidrNum < 0 || cidrNum > 32) {
|
||||||
|
return _('CIDR must be between 0 and 32 in: ' + subnet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
o = s.taboption('basic', form.Flag, 'custom_download_subnets_list_enabled', _('Remote Subnet Lists'), _('Download and use subnet lists from remote URLs'));
|
o = s.taboption('basic', form.Flag, 'custom_download_subnets_list_enabled', _('Remote Subnet Lists'), _('Download and use subnet lists from remote URLs'));
|
||||||
o.default = '0';
|
o.default = '0';
|
||||||
o.rmempty = false;
|
o.rmempty = false;
|
||||||
@@ -315,10 +420,38 @@ return view.extend({
|
|||||||
o.depends('second_enable', '1');
|
o.depends('second_enable', '1');
|
||||||
o.ucisection = 'second';
|
o.ucisection = 'second';
|
||||||
|
|
||||||
o = s.taboption('secondary_config', form.TextValue, 'second_proxy_string', _('Proxy Configuration URL'), _('Enter connection string starting with vless:// or ss:// for proxy configuration'));
|
o = s.taboption('secondary_config', form.ListValue, 'second_proxy_config_type', _('Configuration Type'), _('Select how to configure the proxy'));
|
||||||
|
o.value('url', _('Connection URL'));
|
||||||
|
o.value('outbound', _('Outbound Config'));
|
||||||
|
o.default = 'url';
|
||||||
o.depends('second_mode', 'proxy');
|
o.depends('second_mode', 'proxy');
|
||||||
o.ucisection = 'second';
|
o.ucisection = 'second';
|
||||||
|
|
||||||
|
o = s.taboption('secondary_config', form.TextValue, 'second_proxy_string', _('Proxy Configuration URL'), _('Enter connection string starting with vless:// or ss:// for proxy configuration'));
|
||||||
|
o.depends('second_proxy_config_type', 'url');
|
||||||
|
o.rows = 5;
|
||||||
|
o.ucisection = 'second';
|
||||||
|
|
||||||
|
o = s.taboption('secondary_config', form.TextValue, 'second_outbound_json', _('Outbound Configuration'), _('Enter complete outbound configuration in JSON format'));
|
||||||
|
o.depends('second_proxy_config_type', 'outbound');
|
||||||
|
o.rows = 10;
|
||||||
|
o.ucisection = 'second';
|
||||||
|
o.validate = function (section_id, value) {
|
||||||
|
if (!value || value.length === 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(value);
|
||||||
|
if (!parsed.type || !parsed.server || !parsed.server_port) {
|
||||||
|
return _('JSON must contain at least type, server and server_port fields');
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
return _('Invalid JSON format');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
o = s.taboption('secondary_config', form.ListValue, 'second_interface', _('Network Interface'), _('Select network interface for VPN connection'));
|
o = s.taboption('secondary_config', form.ListValue, 'second_interface', _('Network Interface'), _('Select network interface for VPN connection'));
|
||||||
o.depends('second_mode', 'vpn');
|
o.depends('second_mode', 'vpn');
|
||||||
o.ucisection = 'second';
|
o.ucisection = 'second';
|
||||||
@@ -354,15 +487,18 @@ return view.extend({
|
|||||||
o.rmempty = false;
|
o.rmempty = false;
|
||||||
o.ucisection = 'second';
|
o.ucisection = 'second';
|
||||||
|
|
||||||
o = s.taboption('secondary_config', form.Flag, 'second_custom_domains_list_enabled', _('User Domain List'), _('Enable and manage your custom list of domains for selective routing'));
|
o = s.taboption('secondary_config', form.ListValue, 'second_custom_domains_list_enabled', _('User Domain List Type'), _('Select how to add your custom domains'));
|
||||||
o.default = '0';
|
o.value('disabled', _('Disabled'));
|
||||||
|
o.value('dynamic', _('Dynamic List'));
|
||||||
|
o.value('text', _('Text List'));
|
||||||
|
o.default = 'disabled';
|
||||||
o.rmempty = false;
|
o.rmempty = false;
|
||||||
o.depends('second_enable', '1');
|
o.depends('second_enable', '1');
|
||||||
o.ucisection = 'second';
|
o.ucisection = 'second';
|
||||||
|
|
||||||
o = s.taboption('secondary_config', form.DynamicList, 'second_custom_domains', _('User Domains'), _('Enter domain names without protocols (example: sub.example.com or example.com)'));
|
o = s.taboption('secondary_config', form.DynamicList, 'second_custom_domains', _('User Domains'), _('Enter domain names without protocols (example: sub.example.com or example.com)'));
|
||||||
o.placeholder = 'Domains list';
|
o.placeholder = 'Domains list';
|
||||||
o.depends('second_custom_domains_list_enabled', '1');
|
o.depends('second_custom_domains_list_enabled', 'dynamic');
|
||||||
o.rmempty = false;
|
o.rmempty = false;
|
||||||
o.ucisection = 'second';
|
o.ucisection = 'second';
|
||||||
o.validate = function (section_id, value) {
|
o.validate = function (section_id, value) {
|
||||||
@@ -378,15 +514,10 @@ return view.extend({
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
o = s.taboption('secondary_config', form.Flag, 'second_custom_subnets_list_enabled', _('User Subnet List'), _('Enable and manage your custom list of IP subnets for selective routing'));
|
o = s.taboption('secondary_config', form.TextValue, 'second_custom_domains_text', _('User Domains List'), _('Enter domain names separated by comma, space or newline (example: sub.example.com, example.com or one domain per line)'));
|
||||||
o.default = '0';
|
o.placeholder = 'example.com, sub.example.com\ndomain.com test.com\nsubdomain.domain.com another.com, third.com';
|
||||||
o.rmempty = false;
|
o.depends('second_custom_domains_list_enabled', 'text');
|
||||||
o.depends('second_enable', '1');
|
o.rows = 10;
|
||||||
o.ucisection = 'second';
|
|
||||||
|
|
||||||
o = s.taboption('secondary_config', form.DynamicList, 'second_custom_subnets', _('User Subnets'), _('Enter subnet in CIDR notation (example: 103.21.244.0/22)'));
|
|
||||||
o.placeholder = 'Subnets list';
|
|
||||||
o.depends('second_custom_subnets_list_enabled', '1');
|
|
||||||
o.rmempty = false;
|
o.rmempty = false;
|
||||||
o.ucisection = 'second';
|
o.ucisection = 'second';
|
||||||
o.validate = function (section_id, value) {
|
o.validate = function (section_id, value) {
|
||||||
@@ -394,15 +525,47 @@ return view.extend({
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const subnetRegex = /^(\d{1,3}\.){3}\d{1,3}\/\d{1,2}$/;
|
const domains = value.split(/[,\s\n]/)
|
||||||
|
.map(d => d.trim())
|
||||||
|
.filter(d => d.length > 0);
|
||||||
|
|
||||||
|
const domainRegex = /^(?!-)[A-Za-z0-9-]+([-.][A-Za-z0-9-]+)*\.[A-Za-z]{2,}$/;
|
||||||
|
|
||||||
|
for (const domain of domains) {
|
||||||
|
if (!domainRegex.test(domain)) {
|
||||||
|
return _('Invalid domain format: ' + domain + '. Enter domain without protocol');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
o = s.taboption('secondary_config', form.ListValue, 'second_custom_subnets_list_enabled', _('User Subnet List Type'), _('Select how to add your custom subnets'));
|
||||||
|
o.value('disabled', _('Disabled'));
|
||||||
|
o.value('dynamic', _('Dynamic List'));
|
||||||
|
o.value('text', _('Text List'));
|
||||||
|
o.default = 'disabled';
|
||||||
|
o.rmempty = false;
|
||||||
|
o.depends('second_enable', '1');
|
||||||
|
o.ucisection = 'second';
|
||||||
|
|
||||||
|
o = s.taboption('secondary_config', form.DynamicList, 'second_custom_subnets', _('User Subnets'), _('Enter subnets in CIDR notation (example: 103.21.244.0/22) or single IP addresses'));
|
||||||
|
o.placeholder = 'IP or subnet';
|
||||||
|
o.depends('second_custom_subnets_list_enabled', 'dynamic');
|
||||||
|
o.rmempty = false;
|
||||||
|
o.ucisection = 'second';
|
||||||
|
o.validate = function (section_id, value) {
|
||||||
|
if (!value || value.length === 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const subnetRegex = /^(\d{1,3}\.){3}\d{1,3}(\/\d{1,2})?$/;
|
||||||
|
|
||||||
if (!subnetRegex.test(value)) {
|
if (!subnetRegex.test(value)) {
|
||||||
return _('Invalid subnet format. Use format: X.X.X.X/Y (like 103.21.244.0/22)');
|
return _('Invalid format. Use format: X.X.X.X or X.X.X.X/Y');
|
||||||
}
|
}
|
||||||
|
|
||||||
const [ip, cidr] = value.split('/');
|
const [ip, cidr] = value.split('/');
|
||||||
const ipParts = ip.split('.');
|
const ipParts = ip.split('.');
|
||||||
const cidrNum = parseInt(cidr);
|
|
||||||
|
|
||||||
for (const part of ipParts) {
|
for (const part of ipParts) {
|
||||||
const num = parseInt(part);
|
const num = parseInt(part);
|
||||||
@@ -411,13 +574,58 @@ return view.extend({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cidrNum < 0 || cidrNum > 32) {
|
if (cidr !== undefined) {
|
||||||
return _('CIDR must be between 0 and 32');
|
const cidrNum = parseInt(cidr);
|
||||||
|
if (cidrNum < 0 || cidrNum > 32) {
|
||||||
|
return _('CIDR must be between 0 and 32');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
o = s.taboption('secondary_config', form.TextValue, 'second_custom_subnets_text', _('User Subnets List'), _('Enter subnets in CIDR notation or single IP addresses, separated by comma, space or newline'));
|
||||||
|
o.placeholder = '103.21.244.0/22\n8.8.8.8\n1.1.1.1/32, 9.9.9.9 10.10.10.10';
|
||||||
|
o.depends('second_custom_subnets_list_enabled', 'text');
|
||||||
|
o.rows = 10;
|
||||||
|
o.rmempty = false;
|
||||||
|
o.ucisection = 'second';
|
||||||
|
o.validate = function (section_id, value) {
|
||||||
|
if (!value || value.length === 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const subnets = value.split(/[,\s\n]/)
|
||||||
|
.map(s => s.trim())
|
||||||
|
.filter(s => s.length > 0);
|
||||||
|
|
||||||
|
const subnetRegex = /^(\d{1,3}\.){3}\d{1,3}(\/\d{1,2})?$/;
|
||||||
|
|
||||||
|
for (const subnet of subnets) {
|
||||||
|
if (!subnetRegex.test(subnet)) {
|
||||||
|
return _('Invalid format: ' + subnet + '. Use format: X.X.X.X or X.X.X.X/Y');
|
||||||
|
}
|
||||||
|
|
||||||
|
const [ip, cidr] = subnet.split('/');
|
||||||
|
const ipParts = ip.split('.');
|
||||||
|
|
||||||
|
for (const part of ipParts) {
|
||||||
|
const num = parseInt(part);
|
||||||
|
if (num < 0 || num > 255) {
|
||||||
|
return _('IP parts must be between 0 and 255 in: ' + subnet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cidr !== undefined) {
|
||||||
|
const cidrNum = parseInt(cidr);
|
||||||
|
if (cidrNum < 0 || cidrNum > 32) {
|
||||||
|
return _('CIDR must be between 0 and 32 in: ' + subnet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
return m.render();
|
return m.render();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -218,4 +218,76 @@ msgid "CIDR must be between 0 and 32"
|
|||||||
msgstr "CIDR должен быть между 0 и 32"
|
msgstr "CIDR должен быть между 0 и 32"
|
||||||
|
|
||||||
msgid "Invalid IP format. Use format: X.X.X.X (like 192.168.1.1)"
|
msgid "Invalid IP format. Use format: X.X.X.X (like 192.168.1.1)"
|
||||||
msgstr "Неверный формат IP. Используйте формат: X.X.X.X (например: 192.168.1.1)"
|
msgstr "Неверный формат IP. Используйте формат: X.X.X.X (например: 192.168.1.1)"
|
||||||
|
|
||||||
|
msgid "User Domain List Type"
|
||||||
|
msgstr "Тип пользовательского списка доменов"
|
||||||
|
|
||||||
|
msgid "Select how to add your custom domains"
|
||||||
|
msgstr "Выберите способ добавления пользовательских доменов"
|
||||||
|
|
||||||
|
msgid "Disabled"
|
||||||
|
msgstr "Отключено"
|
||||||
|
|
||||||
|
msgid "Dynamic List"
|
||||||
|
msgstr "Динамический список"
|
||||||
|
|
||||||
|
msgid "Text List"
|
||||||
|
msgstr "Текстовый список"
|
||||||
|
|
||||||
|
msgid "User Domains List"
|
||||||
|
msgstr "Список пользовательских доменов"
|
||||||
|
|
||||||
|
msgid "Enter domain names separated by comma, space or newline (example: sub.example.com, example.com or one domain per line)"
|
||||||
|
msgstr "Введите имена доменов через запятую, пробел или новую строку (пример: sub.example.com, example.com или один домен на строку)"
|
||||||
|
|
||||||
|
msgid "Invalid domain format: %s. Enter domain without protocol"
|
||||||
|
msgstr "Неверный формат домена: %s. Введите домен без протокола"
|
||||||
|
|
||||||
|
msgid "User Subnet List Type"
|
||||||
|
msgstr "Тип пользовательского списка подсетей"
|
||||||
|
|
||||||
|
msgid "Select how to add your custom subnets"
|
||||||
|
msgstr "Выберите способ добавления пользовательских подсетей"
|
||||||
|
|
||||||
|
msgid "Text List (comma/space/newline separated)"
|
||||||
|
msgstr "Текстовый список (разделенный запятыми/пробелами/новыми строками)"
|
||||||
|
|
||||||
|
msgid "Enter subnets in CIDR notation (example: 103.21.244.0/22) or single IP addresses"
|
||||||
|
msgstr "Введите подсети в нотации CIDR (пример: 103.21.244.0/22) или отдельные IP-адреса"
|
||||||
|
|
||||||
|
msgid "User Subnets List"
|
||||||
|
msgstr "Список пользовательских подсетей"
|
||||||
|
|
||||||
|
msgid "Enter subnets in CIDR notation or single IP addresses, separated by comma, space or newline"
|
||||||
|
msgstr "Введите подсети в нотации CIDR или отдельные IP-адреса через запятую, пробел или новую строку"
|
||||||
|
|
||||||
|
msgid "Invalid format. Use format: X.X.X.X or X.X.X.X/Y"
|
||||||
|
msgstr "Неверный формат. Используйте формат: X.X.X.X или X.X.X.X/Y"
|
||||||
|
|
||||||
|
msgid "IP parts must be between 0 and 255 in: %s"
|
||||||
|
msgstr "Части IP-адреса должны быть между 0 и 255 в: %s"
|
||||||
|
|
||||||
|
msgid "Configuration Type"
|
||||||
|
msgstr "Тип конфигурации"
|
||||||
|
|
||||||
|
msgid "Select how to configure the proxy"
|
||||||
|
msgstr "Выберите способ настройки прокси"
|
||||||
|
|
||||||
|
msgid "Connection URL"
|
||||||
|
msgstr "URL подключения"
|
||||||
|
|
||||||
|
msgid "Outbound Config"
|
||||||
|
msgstr "Конфигурация Outbound"
|
||||||
|
|
||||||
|
msgid "Outbound Configuration"
|
||||||
|
msgstr "Конфигурация исходящего соединения"
|
||||||
|
|
||||||
|
msgid "Enter complete outbound configuration in JSON format"
|
||||||
|
msgstr "Введите полную конфигурацию исходящего соединения в формате JSON"
|
||||||
|
|
||||||
|
msgid "JSON must contain at least type, server and server_port fields"
|
||||||
|
msgstr "JSON должен содержать как минимум поля type, server и server_port"
|
||||||
|
|
||||||
|
msgid "Invalid JSON format"
|
||||||
|
msgstr "Неверный формат JSON"
|
||||||
@@ -218,4 +218,76 @@ msgid "CIDR must be between 0 and 32"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Invalid IP format. Use format: X.X.X.X (like 192.168.1.1)"
|
msgid "Invalid IP format. Use format: X.X.X.X (like 192.168.1.1)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "User Domain List Type"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Select how to add your custom domains"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Disabled"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Dynamic List"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Text List"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "User Domains List"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Enter domain names separated by comma, space or newline (example: sub.example.com, example.com or one domain per line)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Invalid domain format: %s. Enter domain without protocol"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "User Subnet List Type"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Select how to add your custom subnets"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Text List (comma/space/newline separated)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Enter subnets in CIDR notation (example: 103.21.244.0/22) or single IP addresses"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "User Subnets List"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Enter subnets in CIDR notation or single IP addresses, separated by comma, space or newline"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Invalid format. Use format: X.X.X.X or X.X.X.X/Y"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "IP parts must be between 0 and 255 in: %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Configuration Type"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Select how to configure the proxy"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Connection URL"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Outbound Config"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Outbound Configuration"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Enter complete outbound configuration in JSON format"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "JSON must contain at least type, server and server_port fields"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Invalid JSON format"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -50,9 +50,6 @@ define Package/podkop/install
|
|||||||
$(INSTALL_DIR) $(1)/etc/config
|
$(INSTALL_DIR) $(1)/etc/config
|
||||||
$(INSTALL_CONF) ./files/etc/config/podkop $(1)/etc/config/podkop
|
$(INSTALL_CONF) ./files/etc/config/podkop $(1)/etc/config/podkop
|
||||||
|
|
||||||
$(INSTALL_DIR) $(1)/etc/podkop
|
|
||||||
$(INSTALL_DATA) ./files/etc/podkop/* $(1)/etc/podkop/
|
|
||||||
|
|
||||||
$(INSTALL_DIR) $(1)/etc/hotplug.d/iface
|
$(INSTALL_DIR) $(1)/etc/hotplug.d/iface
|
||||||
$(INSTALL_DATA) ./files/etc/hotplug.d/iface/50-podkop $(1)/etc/hotplug.d/iface/50-podkop
|
$(INSTALL_DATA) ./files/etc/hotplug.d/iface/50-podkop $(1)/etc/hotplug.d/iface/50-podkop
|
||||||
endef
|
endef
|
||||||
|
|||||||
@@ -1,19 +1,23 @@
|
|||||||
config main 'main'
|
config main 'main'
|
||||||
option mode ''
|
option mode ''
|
||||||
option interface ''
|
option interface ''
|
||||||
option proxy_string ''
|
option proxy_config_type ''
|
||||||
|
#option outbound_json ''
|
||||||
|
#option proxy_string ''
|
||||||
option domain_list_enabled '1'
|
option domain_list_enabled '1'
|
||||||
option domain_list 'ru_inside'
|
option domain_list 'ru_inside'
|
||||||
option subnets_list_enabled '0'
|
option subnets_list_enabled '0'
|
||||||
#list subnets 'twitter'
|
#list subnets 'twitter'
|
||||||
option custom_domains_list_enabled '0'
|
option custom_domains_list_type 'disable'
|
||||||
#list custom_domains ''
|
#list custom_domains ''
|
||||||
|
#option custom_domains_text ''
|
||||||
option custom_local_domains_list_enabled '0'
|
option custom_local_domains_list_enabled '0'
|
||||||
#list custom_local_domains ''
|
#list custom_local_domains ''
|
||||||
option custom_download_domains_list_enabled '0'
|
option custom_download_domains_list_enabled '0'
|
||||||
#list custom_download_domains ''
|
#list custom_download_domains ''
|
||||||
option custom_subnets_list_enabled '0'
|
option custom_domains_list_type 'disable'
|
||||||
#list custom_subnets ''
|
#list custom_subnets ''
|
||||||
|
#custom_subnets_text ''
|
||||||
option custom_download_subnets_list_enabled '0'
|
option custom_download_subnets_list_enabled '0'
|
||||||
#list custom_download_subnets ''
|
#list custom_download_subnets ''
|
||||||
option all_traffic_from_ip_enabled '0'
|
option all_traffic_from_ip_enabled '0'
|
||||||
@@ -26,15 +30,20 @@ config main 'main'
|
|||||||
option socks5 '0'
|
option socks5 '0'
|
||||||
option exclude_ntp '0'
|
option exclude_ntp '0'
|
||||||
option update_interval ''
|
option update_interval ''
|
||||||
|
option custom_domains_text
|
||||||
|
|
||||||
config second 'second'
|
config second 'second'
|
||||||
option second_enable '0'
|
option second_enable '0'
|
||||||
option second_mode 'proxy'
|
option second_mode 'proxy'
|
||||||
option second_interface ''
|
option second_interface ''
|
||||||
option second_proxy_string ''
|
option second_proxy_config_type ''
|
||||||
|
#option second_outbound_json ''
|
||||||
|
#option second_proxy_string ''
|
||||||
option second_domain_service_enabled '0'
|
option second_domain_service_enabled '0'
|
||||||
#list second_service_list 'youtube'
|
#list second_service_list 'youtube'
|
||||||
option second_custom_domains_list_enabled '0'
|
option second_custom_domains_type 'disable'
|
||||||
#list second_custom_domains 'ifconfig.io'
|
#list second_custom_domains 'ifconfig.io'
|
||||||
option second_custom_subnets_list_enabled '0'
|
#option second_custom_domains_text ''
|
||||||
#list second_custom_subnets ''
|
option second_custom_subnets_type 'disable'
|
||||||
|
#list second_custom_subnets ''
|
||||||
|
#porion second_custom_subnets_text ''
|
||||||
@@ -37,14 +37,27 @@ start_service() {
|
|||||||
config_get_bool second_enable "second" "second_enable" "0"
|
config_get_bool second_enable "second" "second_enable" "0"
|
||||||
config_get second_mode "second" "second_mode" "0"
|
config_get second_mode "second" "second_mode" "0"
|
||||||
if [ "$second_enable" -eq "1" ] && [ "$second_mode" = "proxy" ]; then
|
if [ "$second_enable" -eq "1" ] && [ "$second_mode" = "proxy" ]; then
|
||||||
config_get proxy_string "second" "second_proxy_string"
|
config_get proxy_config_type "second" "second_proxy_config_type"
|
||||||
if [[ "$proxy_string" =~ ^ss:// ]]; then
|
|
||||||
sing_box_config_shadowsocks "$proxy_string" "1603"
|
if [ "$proxy_config_type" = "outbound" ]; then
|
||||||
elif [[ "$proxy_string" =~ ^vless:// ]]; then
|
config_get outbound_json "second" "second_outbound_json"
|
||||||
sing_box_config_vless "$proxy_string" "1603"
|
if [ -n "$outbound_json" ]; then
|
||||||
|
log "Using JSON outbound configuration for second proxy"
|
||||||
|
sing_box_config_outbound_json "$outbound_json" "1603"
|
||||||
|
else
|
||||||
|
log "Missing outbound JSON configuration"
|
||||||
|
return
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
log "Unsupported proxy type: $proxy_string"
|
config_get proxy_string "second" "second_proxy_string"
|
||||||
return
|
if [[ "$proxy_string" =~ ^ss:// ]]; then
|
||||||
|
sing_box_config_shadowsocks "$proxy_string" "1603"
|
||||||
|
elif [[ "$proxy_string" =~ ^vless:// ]]; then
|
||||||
|
sing_box_config_vless "$proxy_string" "1603"
|
||||||
|
else
|
||||||
|
log "Unsupported proxy type or missing configuration"
|
||||||
|
return
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
add_route_tproxy podkop2
|
add_route_tproxy podkop2
|
||||||
sing_box_config_check
|
sing_box_config_check
|
||||||
@@ -78,28 +91,95 @@ start_service() {
|
|||||||
outbound_main=$(mktemp)
|
outbound_main=$(mktemp)
|
||||||
outbound_second=$(mktemp)
|
outbound_second=$(mktemp)
|
||||||
|
|
||||||
config_get proxy_string main "proxy_string"
|
# Main proxy config
|
||||||
if [[ "$proxy_string" =~ ^ss:// ]]; then
|
config_get proxy_config_type main "proxy_config_type"
|
||||||
sing_box_config_outbound_shadowsocks "$proxy_string" "$outbound_main" main
|
if [ "$proxy_config_type" = "outbound" ]; then
|
||||||
elif [[ "$proxy_string" =~ ^vless:// ]]; then
|
config_get outbound_json main "outbound_json"
|
||||||
sing_box_config_outbound_vless "$proxy_string" "$outbound_main" main
|
if [ -n "$outbound_json" ]; then
|
||||||
|
echo '{"outbounds":[' > "$outbound_main"
|
||||||
|
echo "$outbound_json" | jq '. + {tag: "main"}' >> "$outbound_main"
|
||||||
|
echo ']}' >> "$outbound_main"
|
||||||
|
else
|
||||||
|
log "Missing main outbound JSON configuration"
|
||||||
|
rm -f "$outbound_main" "$outbound_second"
|
||||||
|
return
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
log "Unsupported proxy type: $proxy_string"
|
config_get proxy_string main "proxy_string"
|
||||||
return
|
if [[ "$proxy_string" =~ ^ss:// ]]; then
|
||||||
|
sing_box_config_shadowsocks "$proxy_string" "1602"
|
||||||
|
jq '.outbounds[0] + {tag: "main"} | {outbounds: [.]}' /etc/sing-box/config.json > "$outbound_main"
|
||||||
|
elif [[ "$proxy_string" =~ ^vless:// ]]; then
|
||||||
|
sing_box_config_vless "$proxy_string" "1602"
|
||||||
|
jq '.outbounds[0] + {tag: "main"} | {outbounds: [.]}' /etc/sing-box/config.json > "$outbound_main"
|
||||||
|
else
|
||||||
|
log "Unsupported proxy type or missing configuration for main"
|
||||||
|
rm -f "$outbound_main" "$outbound_second"
|
||||||
|
return
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
config_get proxy_string "second" "second_proxy_string"
|
# Second proxy config
|
||||||
if [[ "$proxy_string" =~ ^ss:// ]]; then
|
config_get proxy_config_type second "second_proxy_config_type"
|
||||||
sing_box_config_outbound_shadowsocks "$proxy_string" "$outbound_second" second
|
if [ "$proxy_config_type" = "outbound" ]; then
|
||||||
elif [[ "$proxy_string" =~ ^vless:// ]]; then
|
config_get outbound_json second "second_outbound_json"
|
||||||
sing_box_config_outbound_vless "$proxy_string" "$outbound_second" second
|
if [ -n "$outbound_json" ]; then
|
||||||
|
echo '{"outbounds":[' > "$outbound_second"
|
||||||
|
echo "$outbound_json" | jq '. + {tag: "second"}' >> "$outbound_second"
|
||||||
|
echo ']}' >> "$outbound_second"
|
||||||
|
else
|
||||||
|
log "Missing second outbound JSON configuration"
|
||||||
|
rm -f "$outbound_main" "$outbound_second"
|
||||||
|
return
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
log "Unsupported proxy type: $proxy_string"
|
config_get proxy_string "second" "second_proxy_string"
|
||||||
return
|
if [[ "$proxy_string" =~ ^ss:// ]]; then
|
||||||
|
sing_box_config_shadowsocks "$proxy_string" "1603"
|
||||||
|
jq '.outbounds[0] + {tag: "second"} | {outbounds: [.]}' /etc/sing-box/config.json > "$outbound_second"
|
||||||
|
elif [[ "$proxy_string" =~ ^vless:// ]]; then
|
||||||
|
sing_box_config_vless "$proxy_string" "1603"
|
||||||
|
jq '.outbounds[0] + {tag: "second"} | {outbounds: [.]}' /etc/sing-box/config.json > "$outbound_second"
|
||||||
|
else
|
||||||
|
log "Unsupported proxy type or missing configuration for second"
|
||||||
|
rm -f "$outbound_main" "$outbound_second"
|
||||||
|
return
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
jq --argjson outbounds "$(jq -s '{"outbounds": (.[0].outbounds + .[1].outbounds)}' "$outbound_main" "$outbound_second")" \
|
jq -s '{
|
||||||
'.outbounds += $outbounds.outbounds' /etc/podkop/sing-box-two-proxy-template.json >/etc/sing-box/config.json
|
"log": {"level": "warn"},
|
||||||
|
"inbounds": [
|
||||||
|
{
|
||||||
|
"type": "tproxy",
|
||||||
|
"listen": "::",
|
||||||
|
"listen_port": 1602,
|
||||||
|
"sniff": false,
|
||||||
|
"tag": "main"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "tproxy",
|
||||||
|
"listen": "::",
|
||||||
|
"listen_port": 1603,
|
||||||
|
"sniff": false,
|
||||||
|
"tag": "second"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outbounds": (.[0].outbounds + .[1].outbounds),
|
||||||
|
"route": {
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"inbound": "main",
|
||||||
|
"outbound": "main"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inbound": "second",
|
||||||
|
"outbound": "second"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"auto_detect_interface": true
|
||||||
|
}
|
||||||
|
}' "$outbound_main" "$outbound_second" > /etc/sing-box/config.json
|
||||||
|
|
||||||
rm -f "$outbound_main" "$outbound_second"
|
rm -f "$outbound_main" "$outbound_second"
|
||||||
|
|
||||||
@@ -111,14 +191,27 @@ start_service() {
|
|||||||
config_get_bool second_enable "second" "second_enable" "0"
|
config_get_bool second_enable "second" "second_enable" "0"
|
||||||
config_get second_mode "second" "second_mode" "0"
|
config_get second_mode "second" "second_mode" "0"
|
||||||
if [ "$second_enable" -eq "0" ] || [ "$second_mode" = "vpn" ]; then
|
if [ "$second_enable" -eq "0" ] || [ "$second_mode" = "vpn" ]; then
|
||||||
config_get proxy_string main "proxy_string"
|
config_get proxy_config_type main "proxy_config_type"
|
||||||
if [[ "$proxy_string" =~ ^ss:// ]]; then
|
|
||||||
sing_box_config_shadowsocks "$proxy_string" "1602"
|
if [ "$proxy_config_type" = "outbound" ]; then
|
||||||
elif [[ "$proxy_string" =~ ^vless:// ]]; then
|
config_get outbound_json main "outbound_json"
|
||||||
sing_box_config_vless "$proxy_string" "1602"
|
if [ -n "$outbound_json" ]; then
|
||||||
|
log "Using JSON outbound configuration"
|
||||||
|
sing_box_config_outbound_json "$outbound_json" "1602"
|
||||||
|
else
|
||||||
|
log "Missing outbound JSON configuration"
|
||||||
|
return
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
log "Unsupported proxy type: $proxy_string"
|
config_get proxy_string main "proxy_string"
|
||||||
return
|
if [[ "$proxy_string" =~ ^ss:// ]]; then
|
||||||
|
sing_box_config_shadowsocks "$proxy_string" "1602"
|
||||||
|
elif [[ "$proxy_string" =~ ^vless:// ]]; then
|
||||||
|
sing_box_config_vless "$proxy_string" "1602"
|
||||||
|
else
|
||||||
|
log "Unsupported proxy type or missing configuration"
|
||||||
|
return
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
add_route_tproxy podkop
|
add_route_tproxy podkop
|
||||||
fi
|
fi
|
||||||
@@ -274,6 +367,7 @@ remove_cron_job() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
list_update() {
|
list_update() {
|
||||||
|
# Main domains processing
|
||||||
config_get_bool domain_list_enabled "main" "domain_list_enabled" "0"
|
config_get_bool domain_list_enabled "main" "domain_list_enabled" "0"
|
||||||
if [ "$domain_list_enabled" -eq 1 ]; then
|
if [ "$domain_list_enabled" -eq 1 ]; then
|
||||||
log "Adding a common domains list"
|
log "Adding a common domains list"
|
||||||
@@ -283,15 +377,24 @@ list_update() {
|
|||||||
dnsmasq_config_check podkop-domains.lst
|
dnsmasq_config_check podkop-domains.lst
|
||||||
fi
|
fi
|
||||||
|
|
||||||
config_get_bool custom_domains_list_enabled "main" "custom_domains_list_enabled" "0"
|
# Main custom domains processing
|
||||||
if [ "$custom_domains_list_enabled" -eq 1 ]; then
|
config_get custom_domains_list_type "main" "custom_domains_list_enabled" "disabled"
|
||||||
|
if [ "$custom_domains_list_type" != "disabled" ]; then
|
||||||
log "Adding a custom domains list"
|
log "Adding a custom domains list"
|
||||||
add_set "podkop_domains" "main"
|
add_set "podkop_domains" "main"
|
||||||
rm -f /tmp/dnsmasq.d/podkop-custom-domains.lst
|
rm -f /tmp/dnsmasq.d/podkop-custom-domains.lst
|
||||||
config_list_foreach main custom_domains "list_custom_domains_create" "podkop"
|
|
||||||
|
if [ "$custom_domains_list_type" = "dynamic" ]; then
|
||||||
|
config_list_foreach main custom_domains "list_custom_domains_create" "podkop"
|
||||||
|
elif [ "$custom_domains_list_type" = "text" ]; then
|
||||||
|
config_get custom_domains_text main "custom_domains_text"
|
||||||
|
process_domains_text "$custom_domains_text" "podkop"
|
||||||
|
fi
|
||||||
|
|
||||||
dnsmasq_config_check podkop-custom-domains.lst
|
dnsmasq_config_check podkop-custom-domains.lst
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Main custom download domains
|
||||||
config_get_bool custom_download_domains_list_enabled "main" "custom_download_domains_list_enabled" "0"
|
config_get_bool custom_download_domains_list_enabled "main" "custom_download_domains_list_enabled" "0"
|
||||||
if [ "$custom_download_domains_list_enabled" -eq 1 ]; then
|
if [ "$custom_download_domains_list_enabled" -eq 1 ]; then
|
||||||
log "Adding a custom domains list from URL"
|
log "Adding a custom domains list from URL"
|
||||||
@@ -299,6 +402,7 @@ list_update() {
|
|||||||
config_list_foreach main custom_download_domains "list_custom_download_domains_create" "podkop"
|
config_list_foreach main custom_download_domains "list_custom_download_domains_create" "podkop"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Main domains delist
|
||||||
config_get_bool custom_local_domains_list_enabled "main" "custom_local_domains_list_enabled" "0"
|
config_get_bool custom_local_domains_list_enabled "main" "custom_local_domains_list_enabled" "0"
|
||||||
if [ "$custom_local_domains_list_enabled" -eq 1 ]; then
|
if [ "$custom_local_domains_list_enabled" -eq 1 ]; then
|
||||||
log "Adding a custom local domain list"
|
log "Adding a custom local domain list"
|
||||||
@@ -313,20 +417,56 @@ list_update() {
|
|||||||
dnsmasq_config_check podkop-domains.lst
|
dnsmasq_config_check podkop-domains.lst
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$domain_list_enabled" -eq 1 ] || [ "$custom_domains_list_enabled" -eq 1 ]; then
|
# Main subnets processing
|
||||||
/etc/init.d/dnsmasq restart
|
config_get_bool subnets_list_enabled "main" "subnets_list_enabled" "0"
|
||||||
|
if [ "$subnets_list_enabled" -eq 1 ]; then
|
||||||
|
log "Adding a subnets from list"
|
||||||
|
mkdir -p /tmp/podkop
|
||||||
|
add_set "podkop_subnets" "main"
|
||||||
|
config_list_foreach main subnets "list_subnets_download"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
config_get_bool second_custom_domains_list_enabled "second" "second_custom_domains_list_enabled" "0"
|
# Main custom subnets
|
||||||
if [ "$second_custom_domains_list_enabled" -eq 1 ]; then
|
config_get custom_subnets_list_type "main" "custom_subnets_list_enabled" "disabled"
|
||||||
|
if [ "$custom_subnets_list_type" != "disabled" ]; then
|
||||||
|
log "Adding a custom subnets list"
|
||||||
|
add_set "podkop_subnets" "main"
|
||||||
|
|
||||||
|
if [ "$custom_subnets_list_type" = "dynamic" ]; then
|
||||||
|
config_list_foreach main custom_subnets list_custom_subnets_preprocess "podkop"
|
||||||
|
elif [ "$custom_subnets_list_type" = "text" ]; then
|
||||||
|
config_get custom_subnets_text main "custom_subnets_text"
|
||||||
|
process_subnets_text "$custom_subnets_text" "podkop"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Main custom download subnets
|
||||||
|
config_get_bool custom_download_subnets_list_enabled "main" "custom_download_subnets_list_enabled" "0"
|
||||||
|
if [ "$custom_download_subnets_list_enabled" -eq 1 ]; then
|
||||||
|
log "Adding a subnets from URL"
|
||||||
|
mkdir -p /tmp/podkop
|
||||||
|
add_set "podkop_subnets" "main"
|
||||||
|
config_list_foreach main custom_download_subnets "list_subnets_download"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Second custom domains processing
|
||||||
|
config_get second_custom_domains_list_type "second" "second_custom_domains_list_enabled" "disabled"
|
||||||
|
if [ "$second_custom_domains_list_type" != "disabled" ]; then
|
||||||
log "Adding a custom domains list. Second podkop"
|
log "Adding a custom domains list. Second podkop"
|
||||||
add_set "podkop2_domains" "second"
|
add_set "podkop2_domains" "second"
|
||||||
rm -f /tmp/dnsmasq.d/podkop2-custom-domains.lst
|
rm -f /tmp/dnsmasq.d/podkop2-custom-domains.lst
|
||||||
config_list_foreach second second_custom_domains "list_delist_domains"
|
|
||||||
config_list_foreach second second_custom_domains "list_custom_domains_create" "podkop2"
|
if [ "$second_custom_domains_list_type" = "dynamic" ]; then
|
||||||
|
config_list_foreach second second_custom_domains "list_custom_domains_create" "podkop2"
|
||||||
|
elif [ "$second_custom_domains_list_type" = "text" ]; then
|
||||||
|
config_get second_custom_domains_text second "second_custom_domains_text"
|
||||||
|
process_domains_text "$second_custom_domains_text" "podkop2"
|
||||||
|
fi
|
||||||
|
|
||||||
dnsmasq_config_check podkop2-custom-domains.lst
|
dnsmasq_config_check podkop2-custom-domains.lst
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Second service domains
|
||||||
config_get_bool second_domain_service_enabled "second" "second_domain_service_enabled" "0"
|
config_get_bool second_domain_service_enabled "second" "second_domain_service_enabled" "0"
|
||||||
if [ "$second_domain_service_enabled" -eq 1 ]; then
|
if [ "$second_domain_service_enabled" -eq 1 ]; then
|
||||||
log "Adding a service for podkop2"
|
log "Adding a service for podkop2"
|
||||||
@@ -337,38 +477,26 @@ list_update() {
|
|||||||
dnsmasq_config_check podkop2-domains.lst
|
dnsmasq_config_check podkop2-domains.lst
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$second_custom_domains_list_enabled" -eq 1 ] || [ "$second_domain_service_enabled" -eq 1 ]; then
|
# Second custom subnets
|
||||||
/etc/init.d/dnsmasq restart
|
config_get second_custom_subnets_list_type "second" "second_custom_subnets_list_enabled" "disabled"
|
||||||
fi
|
if [ "$second_custom_subnets_list_type" != "disabled" ]; then
|
||||||
|
|
||||||
config_get_bool subnets_list_enabled "main" "subnets_list_enabled" "0"
|
|
||||||
if [ "$subnets_list_enabled" -eq 1 ]; then
|
|
||||||
log "Adding a subnets from list"
|
|
||||||
mkdir -p /tmp/podkop
|
|
||||||
add_set "podkop_subnets" "main"
|
|
||||||
config_list_foreach main subnets "list_subnets_download"
|
|
||||||
fi
|
|
||||||
|
|
||||||
config_get_bool custom_download_subnets_list_enabled "main" "custom_download_subnets_list_enabled" "0"
|
|
||||||
if [ "$custom_download_subnets_list_enabled" -eq 1 ]; then
|
|
||||||
log "Adding a subnets from URL"
|
|
||||||
mkdir -p /tmp/podkop
|
|
||||||
add_set "podkop_subnets" "main"
|
|
||||||
config_list_foreach main custom_download_subnets "list_subnets_download"
|
|
||||||
fi
|
|
||||||
|
|
||||||
config_get_bool custom_subnets_list_enabled "main" "custom_subnets_list_enabled" "0"
|
|
||||||
if [ "$custom_subnets_list_enabled" -eq 1 ]; then
|
|
||||||
log "Adding a custom subnets list"
|
|
||||||
add_set "podkop_subnets" "main"
|
|
||||||
config_list_foreach main custom_subnets "list_custom_subnets_create" "podkop"
|
|
||||||
fi
|
|
||||||
|
|
||||||
config_get_bool second_custom_subnets_list_enabled "second" "second_custom_subnets_list_enabled" "0"
|
|
||||||
if [ "$second_custom_subnets_list_enabled" -eq 1 ]; then
|
|
||||||
log "Adding a custom subnets list. Second"
|
log "Adding a custom subnets list. Second"
|
||||||
add_set "podkop2_subnets" "second"
|
add_set "podkop2_subnets" "second"
|
||||||
config_list_foreach second second_custom_subnets "list_custom_subnets_create" "podkop2"
|
|
||||||
|
if [ "$second_custom_subnets_list_type" = "dynamic" ]; then
|
||||||
|
config_list_foreach second second_custom_subnets list_custom_subnets_preprocess "podkop2"
|
||||||
|
elif [ "$second_custom_subnets_list_type" = "text" ]; then
|
||||||
|
config_get second_custom_subnets_text second "second_custom_subnets_text"
|
||||||
|
process_subnets_text "$second_custom_subnets_text" "podkop2"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Restart dnsmasq if needed
|
||||||
|
if [ "$domain_list_enabled" -eq 1 ] || [ "$custom_domains_list_type" != "disabled" ] || \
|
||||||
|
[ "$custom_download_domains_list_enabled" -eq 1 ] || \
|
||||||
|
[ "$second_custom_domains_list_type" != "disabled" ] || \
|
||||||
|
[ "$second_domain_service_enabled" -eq 1 ]; then
|
||||||
|
/etc/init.d/dnsmasq restart
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -745,6 +873,34 @@ dnsmasq_config_check() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sing_box_config_outbound_json() {
|
||||||
|
local json_config="$1"
|
||||||
|
local listen_port="$2"
|
||||||
|
|
||||||
|
cat > /tmp/base_config.json << EOF
|
||||||
|
{
|
||||||
|
"log": {
|
||||||
|
"level": "warn"
|
||||||
|
},
|
||||||
|
"inbounds": [
|
||||||
|
{
|
||||||
|
"type": "tproxy",
|
||||||
|
"listen": "::",
|
||||||
|
"listen_port": $listen_port,
|
||||||
|
"sniff": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outbounds": [],
|
||||||
|
"route": {
|
||||||
|
"auto_detect_interface": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
jq --argjson outbound "$json_config" '.outbounds += [$outbound]' /tmp/base_config.json > /etc/sing-box/config.json
|
||||||
|
rm -f /tmp/base_config.json
|
||||||
|
}
|
||||||
|
|
||||||
sing_box_uci() {
|
sing_box_uci() {
|
||||||
local config="/etc/config/sing-box"
|
local config="/etc/config/sing-box"
|
||||||
if grep -q "option enabled '0'" "$config" ||
|
if grep -q "option enabled '0'" "$config" ||
|
||||||
@@ -762,36 +918,61 @@ sing_box_config_shadowsocks() {
|
|||||||
local STRING="$1"
|
local STRING="$1"
|
||||||
local listen_port="$2"
|
local listen_port="$2"
|
||||||
|
|
||||||
local encrypted_part=$(echo "$STRING" | cut -d'/' -f3 | cut -d'@' -f1 | base64 --decode)
|
# Определяем тип SS (2022 или old) по наличию : в base64 части
|
||||||
local method=$(echo "$encrypted_part" | cut -d':' -f1)
|
if echo "$STRING" | cut -d'/' -f3 | cut -d'@' -f1 | base64 -d 2>/dev/null | grep -q ":"; then
|
||||||
local password=$(echo "$encrypted_part" | cut -d':' -f2-)
|
# Old SS format
|
||||||
|
local encrypted_part=$(echo "$STRING" | cut -d'/' -f3 | cut -d'@' -f1 | base64 --decode)
|
||||||
|
local method=$(echo "$encrypted_part" | cut -d':' -f1)
|
||||||
|
local password=$(echo "$encrypted_part" | cut -d':' -f2-)
|
||||||
|
else
|
||||||
|
# SS 2022 format
|
||||||
|
local method_and_password=$(echo "$STRING" | cut -d'/' -f3 | cut -d'@' -f1)
|
||||||
|
local method=$(echo "$method_and_password" | cut -d':' -f1)
|
||||||
|
local password=$(echo "$method_and_password" | cut -d':' -f2- | sed 's/%3D/=/g')
|
||||||
|
|
||||||
|
# Если method в base64, декодируем
|
||||||
|
if echo "$method" | base64 -d &>/dev/null; then
|
||||||
|
method=$(echo "$method" | base64 -d)
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
local server=$(echo "$STRING" | cut -d'@' -f2 | cut -d':' -f1)
|
local server=$(echo "$STRING" | cut -d'@' -f2 | cut -d':' -f1)
|
||||||
local port=$(echo "$STRING" | sed -n 's|.*:\([0-9]\+\).*|\1|p')
|
local port=$(echo "$STRING" | sed -n 's|.*:\([0-9]\+\).*|\1|p')
|
||||||
local label=$(echo "$STRING" | cut -d'#' -f2)
|
|
||||||
|
|
||||||
template_config="/etc/podkop/sing-box-shadowsocks-template.json"
|
# Create base config
|
||||||
|
cat > /tmp/ss_config.json << EOF
|
||||||
|
{
|
||||||
|
"log": {
|
||||||
|
"level": "warn"
|
||||||
|
},
|
||||||
|
"inbounds": [
|
||||||
|
{
|
||||||
|
"type": "tproxy",
|
||||||
|
"listen": "::",
|
||||||
|
"listen_port": $listen_port,
|
||||||
|
"sniff": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outbounds": [
|
||||||
|
{
|
||||||
|
"type": "shadowsocks",
|
||||||
|
"server": "$server",
|
||||||
|
"server_port": $port,
|
||||||
|
"method": "$method",
|
||||||
|
"password": "$password",
|
||||||
|
"udp_over_tcp": {
|
||||||
|
"enabled": true,
|
||||||
|
"version": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"route": {
|
||||||
|
"auto_detect_interface": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
jq --arg server "$server" \
|
mv /tmp/ss_config.json /etc/sing-box/config.json
|
||||||
--arg port "$port" \
|
|
||||||
--arg method "$method" \
|
|
||||||
--arg password "$password" \
|
|
||||||
--arg listen_port "$listen_port" \
|
|
||||||
'.inbounds[] |=
|
|
||||||
if .type == "tproxy" then
|
|
||||||
.listen_port = ($listen_port | tonumber)
|
|
||||||
else
|
|
||||||
.
|
|
||||||
end |
|
|
||||||
.outbounds[] |=
|
|
||||||
if .type == "shadowsocks" then
|
|
||||||
.server = $server |
|
|
||||||
.server_port = ($port | tonumber) |
|
|
||||||
.method = $method |
|
|
||||||
.password = $password
|
|
||||||
else
|
|
||||||
.
|
|
||||||
end' "$template_config" >/etc/sing-box/config.json
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sing_box_config_vless() {
|
sing_box_config_vless() {
|
||||||
@@ -799,167 +980,106 @@ sing_box_config_vless() {
|
|||||||
local listen_port="$2"
|
local listen_port="$2"
|
||||||
|
|
||||||
get_param() {
|
get_param() {
|
||||||
echo "$STRING" | sed -n "s/.*[?&]$1=\([^&?#]*\).*/\1/p"
|
local param="$1"
|
||||||
|
local value=$(echo "$STRING" | sed -n "s/.*[?&]$param=\([^&?#]*\).*/\1/p")
|
||||||
|
value=$(echo "$value" | sed 's/%2F/\//g; s/%2C/,/g; s/%3D/=/g; s/%2B/+/g; s/%20/ /g' | tr -d '\n' | tr -d '\r')
|
||||||
|
echo "$value"
|
||||||
}
|
}
|
||||||
|
|
||||||
uuid=$(echo "$STRING" | cut -d'/' -f3 | cut -d'@' -f1)
|
uuid=$(echo "$STRING" | cut -d'/' -f3 | cut -d'@' -f1 | tr -d '\n' | tr -d '\r' | sed 's/False//g')
|
||||||
server=$(echo "$STRING" | cut -d'@' -f2 | cut -d':' -f1)
|
server=$(echo "$STRING" | cut -d'@' -f2 | cut -d':' -f1 | tr -d '\n' | tr -d '\r' | sed 's/False//g')
|
||||||
port=$(echo "$STRING" | cut -d'@' -f2 | cut -d':' -f2 | cut -d'?' -f1 | awk -F'/' '{print $1}')
|
port=$(echo "$STRING" | cut -d'@' -f2 | cut -d':' -f2 | cut -d'?' -f1 | cut -d'/' -f1 | cut -d'#' -f1 | tr -d '\n' | tr -d '\r' | sed 's/False//g')
|
||||||
|
|
||||||
type=$(get_param "type")
|
jq -n \
|
||||||
flow=$(get_param "flow")
|
--arg listen_port "$listen_port" \
|
||||||
sni=$(get_param "sni")
|
--arg server "$server" \
|
||||||
fp=$(get_param "fp")
|
--argjson port "$port" \
|
||||||
security=$(get_param "security")
|
--arg uuid "$uuid" \
|
||||||
pbk=$(get_param "pbk")
|
--arg type "$(get_param "type")" \
|
||||||
sid=$(get_param "sid")
|
--arg flow "$(get_param "flow")" \
|
||||||
encoding=$(get_param "packetEncoding")
|
--arg sni "$(get_param "sni")" \
|
||||||
alpn=$(echo "$(get_param "alpn" | sed 's/%2C/,/g; s/%2F/\//g')" | jq -R -s -c 'split(",")' | sed 's/\\n//g')
|
--arg fp "$(get_param "fp")" \
|
||||||
label=$(echo "$STRING" | cut -d'#' -f2)
|
--arg security "$(get_param "security")" \
|
||||||
|
--arg pbk "$(get_param "pbk")" \
|
||||||
|
--arg sid "$(get_param "sid")" \
|
||||||
|
--arg alpn "$(get_param "alpn")" \
|
||||||
|
--arg path "$(get_param "path")" \
|
||||||
|
--arg host "$(get_param "host")" \
|
||||||
|
--arg spx "$(get_param "spx")" \
|
||||||
|
--arg insecure "$(get_param "allowInsecure")" \
|
||||||
|
'{
|
||||||
|
"log": {
|
||||||
|
"level": "warn"
|
||||||
|
},
|
||||||
|
"inbounds": [
|
||||||
|
{
|
||||||
|
"type": "tproxy",
|
||||||
|
"listen": "::",
|
||||||
|
"listen_port": ($listen_port|tonumber),
|
||||||
|
"sniff": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outbounds": [
|
||||||
|
{
|
||||||
|
"type": "vless",
|
||||||
|
"server": $server,
|
||||||
|
"server_port": ($port|tonumber),
|
||||||
|
"uuid": $uuid,
|
||||||
|
"packet_encoding": "",
|
||||||
|
"domain_strategy": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"route": {
|
||||||
|
"auto_detect_interface": true
|
||||||
|
}
|
||||||
|
} |
|
||||||
|
|
||||||
template_config="/etc/podkop/sing-box-vless-template.json"
|
if $flow != "" then .outbounds[0].flow = $flow else . end |
|
||||||
|
|
||||||
jq --arg server "$server" \
|
if $type == "ws" then
|
||||||
--arg port "$port" \
|
.outbounds[0].transport = {
|
||||||
--arg uuid "$uuid" \
|
"type": "ws",
|
||||||
--arg type "$type" \
|
"path": $path
|
||||||
--arg flow "$flow" \
|
} |
|
||||||
--arg sni "$sni" \
|
if $host != "" then
|
||||||
--arg fp "$fp" \
|
.outbounds[0].transport.headers = {
|
||||||
--arg security "$security" \
|
"Host": $host
|
||||||
--arg pbk "$pbk" \
|
}
|
||||||
--arg sid "$sid" \
|
else . end
|
||||||
--argjson alpn "$alpn" \
|
elif $type == "grpc" then
|
||||||
--arg encoding "$encoding" \
|
.outbounds[0].transport = {
|
||||||
--arg listen_port "$listen_port" \
|
"type": "grpc"
|
||||||
'.inbounds[] |=
|
}
|
||||||
if .type == "tproxy" then
|
else . end |
|
||||||
.listen_port = ($listen_port | tonumber)
|
|
||||||
else
|
|
||||||
.
|
|
||||||
end |
|
|
||||||
.outbounds[] |=
|
|
||||||
(.server = $server |
|
|
||||||
.server_port = ($port | tonumber) |
|
|
||||||
.uuid = $uuid |
|
|
||||||
if $security == "reality" then
|
|
||||||
if $flow == "" then del(.flow) else .flow = $flow end |
|
|
||||||
if $encoding == "" then del(.packet_encoding) else .packet_encoding = $encoding end |
|
|
||||||
.tls.server_name = $sni |
|
|
||||||
.tls.utls.fingerprint = $fp |
|
|
||||||
.tls.reality.public_key = $pbk |
|
|
||||||
.tls.reality.short_id = $sid
|
|
||||||
elif $security == "tls" then
|
|
||||||
.tls.alpn = $alpn |
|
|
||||||
.tls.server_name = $sni |
|
|
||||||
del(.flow) |
|
|
||||||
del(.tls.utls) |
|
|
||||||
del(.tls.reality)
|
|
||||||
elif $security == "" or $security == "none" then
|
|
||||||
del(.flow) |
|
|
||||||
del(.tls)
|
|
||||||
else
|
|
||||||
.
|
|
||||||
end)' "$template_config" >/etc/sing-box/config.json
|
|
||||||
}
|
|
||||||
|
|
||||||
sing_box_config_outbound_shadowsocks() {
|
if $security == "reality" or $security == "tls" then
|
||||||
local STRING="$1"
|
.outbounds[0].tls = {
|
||||||
local outbound="$2"
|
"enabled": true,
|
||||||
local name="$3"
|
"server_name": $sni,
|
||||||
|
"utls": {
|
||||||
|
"enabled": true,
|
||||||
|
"fingerprint": $fp
|
||||||
|
},
|
||||||
|
"insecure": ($insecure == "1")
|
||||||
|
} |
|
||||||
|
if $alpn != "" then
|
||||||
|
.outbounds[0].tls.alpn = ($alpn | split(","))
|
||||||
|
else . end |
|
||||||
|
if $security == "reality" then
|
||||||
|
.outbounds[0].tls.reality = {
|
||||||
|
"enabled": true,
|
||||||
|
"public_key": $pbk,
|
||||||
|
"short_id": $sid
|
||||||
|
}
|
||||||
|
else . end
|
||||||
|
else . end' > /etc/sing-box/config.json
|
||||||
|
|
||||||
local encrypted_part=$(echo "$STRING" | cut -d'/' -f3 | cut -d'@' -f1 | base64 --decode)
|
if [ $? -eq 0 ]; then
|
||||||
local method=$(echo "$encrypted_part" | cut -d':' -f1)
|
echo "Config created successfully"
|
||||||
local password=$(echo "$encrypted_part" | cut -d':' -f2-)
|
else
|
||||||
|
echo "Error: Invalid JSON config generated"
|
||||||
local server=$(echo "$STRING" | cut -d'@' -f2 | cut -d':' -f1)
|
return 1
|
||||||
local port=$(echo "$STRING" | cut -d':' -f3 | cut -d'#' -f1)
|
fi
|
||||||
label=$(echo "$STRING" | cut -d'#' -f2)
|
|
||||||
|
|
||||||
template_config="/etc/podkop/sing-box-shadowsocks-outbound-template.json"
|
|
||||||
|
|
||||||
jq --arg server "$server" \
|
|
||||||
--arg port "$port" \
|
|
||||||
--arg method "$method" \
|
|
||||||
--arg password "$password" \
|
|
||||||
--arg tag "$name" \
|
|
||||||
'.outbounds[] |=
|
|
||||||
if .type == "shadowsocks" then
|
|
||||||
.server = $server |
|
|
||||||
.server_port = ($port | tonumber) |
|
|
||||||
.method = $method |
|
|
||||||
.password = $password |
|
|
||||||
.tag = $tag
|
|
||||||
else
|
|
||||||
.
|
|
||||||
end' "$template_config" >$outbound
|
|
||||||
}
|
|
||||||
|
|
||||||
sing_box_config_outbound_vless() {
|
|
||||||
local STRING="$1"
|
|
||||||
local outbound="$2"
|
|
||||||
local name="$3"
|
|
||||||
|
|
||||||
get_param() {
|
|
||||||
echo "$STRING" | sed -n "s/.*[?&]$1=\([^&?#]*\).*/\1/p"
|
|
||||||
}
|
|
||||||
|
|
||||||
uuid=$(echo "$STRING" | cut -d'/' -f3 | cut -d'@' -f1)
|
|
||||||
server=$(echo "$STRING" | cut -d'@' -f2 | cut -d':' -f1)
|
|
||||||
port=$(echo "$STRING" | cut -d'@' -f2 | cut -d':' -f2 | cut -d'?' -f1 | awk -F'/' '{print $1}')
|
|
||||||
|
|
||||||
type=$(get_param "type")
|
|
||||||
flow=$(get_param "flow")
|
|
||||||
sni=$(get_param "sni")
|
|
||||||
fp=$(get_param "fp")
|
|
||||||
security=$(get_param "security")
|
|
||||||
pbk=$(get_param "pbk")
|
|
||||||
sid=$(get_param "sid")
|
|
||||||
alpn=$(echo "$(get_param "alpn" | sed 's/%2C/,/g; s/%2F/\//g')" | jq -R -s -c 'split(",")' | sed 's/\\n//g')
|
|
||||||
encoding=$(get_param "packetEncoding")
|
|
||||||
label=$(echo "$STRING" | cut -d'#' -f2)
|
|
||||||
|
|
||||||
template_config="/etc/podkop/sing-box-vless-outbound-template.json"
|
|
||||||
|
|
||||||
jq --arg server "$server" \
|
|
||||||
--arg port "$port" \
|
|
||||||
--arg uuid "$uuid" \
|
|
||||||
--arg type "$type" \
|
|
||||||
--arg flow "$flow" \
|
|
||||||
--arg sni "$sni" \
|
|
||||||
--arg fp "$fp" \
|
|
||||||
--arg security "$security" \
|
|
||||||
--arg pbk "$pbk" \
|
|
||||||
--arg sid "$sid" \
|
|
||||||
--argjson alpn "$alpn" \
|
|
||||||
--arg encoding "$encoding" \
|
|
||||||
--arg tag "$name" \
|
|
||||||
'.outbounds[] |=
|
|
||||||
(.server = $server |
|
|
||||||
.server_port = ($port | tonumber) |
|
|
||||||
.uuid = $uuid |
|
|
||||||
if $security == "reality" then
|
|
||||||
if $flow == "" then del(.flow) else .flow = $flow end |
|
|
||||||
if $encoding == "" then del(.packet_encoding) else .packet_encoding = $encoding end |
|
|
||||||
.tls.server_name = $sni |
|
|
||||||
.tls.utls.fingerprint = $fp |
|
|
||||||
.tls.reality.public_key = $pbk |
|
|
||||||
.tls.reality.short_id = $sid |
|
|
||||||
.tag = $tag
|
|
||||||
elif $security == "tls" then
|
|
||||||
.tls.alpn = $alpn |
|
|
||||||
.tls.server_name = $sni |
|
|
||||||
del(.flow) |
|
|
||||||
del(.tls.utls) |
|
|
||||||
del(.tls.reality) |
|
|
||||||
.tag = $tag
|
|
||||||
elif $security == "" or $security == "none" then
|
|
||||||
del(.flow) |
|
|
||||||
del(.tls) |
|
|
||||||
.tag = $tag
|
|
||||||
else
|
|
||||||
.
|
|
||||||
end)' "$template_config" >$outbound
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sing_box_config_check() {
|
sing_box_config_check() {
|
||||||
@@ -967,4 +1087,51 @@ sing_box_config_check() {
|
|||||||
log "Sing-box configuration is invalid"
|
log "Sing-box configuration is invalid"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
process_domains_text() {
|
||||||
|
local text="$1"
|
||||||
|
local name="$2"
|
||||||
|
|
||||||
|
local tmp_file=$(mktemp)
|
||||||
|
echo "$text" > "$tmp_file"
|
||||||
|
|
||||||
|
sed 's/[, ]\+/\n/g' "$tmp_file" | while IFS= read -r domain; do
|
||||||
|
domain=$(echo "$domain" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
||||||
|
if [ -n "$domain" ]; then
|
||||||
|
list_custom_domains_create "$domain" "$name"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
rm -f "$tmp_file"
|
||||||
|
}
|
||||||
|
|
||||||
|
process_subnets_text() {
|
||||||
|
local text="$1"
|
||||||
|
local name="$2"
|
||||||
|
|
||||||
|
local tmp_file=$(mktemp)
|
||||||
|
echo "$text" > "$tmp_file"
|
||||||
|
|
||||||
|
sed 's/[, ]\+/\n/g' "$tmp_file" | while IFS= read -r subnet; do
|
||||||
|
subnet=$(echo "$subnet" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
||||||
|
if [ -n "$subnet" ]; then
|
||||||
|
if ! echo "$subnet" | grep -q "/"; then
|
||||||
|
subnet="$subnet/32"
|
||||||
|
fi
|
||||||
|
list_custom_subnets_create "$subnet" "$name"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
rm -f "$tmp_file"
|
||||||
|
}
|
||||||
|
|
||||||
|
list_custom_subnets_preprocess() {
|
||||||
|
local subnet="$1"
|
||||||
|
local name="$2"
|
||||||
|
|
||||||
|
if ! echo "$subnet" | grep -q "/"; then
|
||||||
|
subnet="$subnet/32"
|
||||||
|
fi
|
||||||
|
list_custom_subnets_create "$subnet" "$name"
|
||||||
}
|
}
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
{
|
|
||||||
"outbounds": [
|
|
||||||
{
|
|
||||||
"type": "shadowsocks",
|
|
||||||
"server": "$HOST",
|
|
||||||
"server_port": "$PORT",
|
|
||||||
"method": "$METHOD",
|
|
||||||
"password": "$PASS",
|
|
||||||
"udp_over_tcp": {
|
|
||||||
"enabled": true,
|
|
||||||
"version": 2
|
|
||||||
},
|
|
||||||
"tag": "$TAG"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
{
|
|
||||||
"log": {
|
|
||||||
"level": "warn"
|
|
||||||
},
|
|
||||||
"inbounds": [
|
|
||||||
{
|
|
||||||
"type": "tproxy",
|
|
||||||
"listen": "::",
|
|
||||||
"listen_port": 1602,
|
|
||||||
"sniff": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"outbounds": [
|
|
||||||
{
|
|
||||||
"type": "shadowsocks",
|
|
||||||
"server": "$HOST",
|
|
||||||
"server_port": "$PORT",
|
|
||||||
"method": "$METHOD",
|
|
||||||
"password": "$PASS",
|
|
||||||
"udp_over_tcp": {
|
|
||||||
"enabled": true,
|
|
||||||
"version": 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"route": {
|
|
||||||
"auto_detect_interface": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
{
|
|
||||||
"log": {
|
|
||||||
"level": "warn"
|
|
||||||
},
|
|
||||||
"inbounds": [
|
|
||||||
{
|
|
||||||
"type": "tproxy",
|
|
||||||
"listen": "::",
|
|
||||||
"listen_port": 1602,
|
|
||||||
"sniff": false,
|
|
||||||
"tag": "main"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "tproxy",
|
|
||||||
"listen": "::",
|
|
||||||
"listen_port": 1603,
|
|
||||||
"sniff": false,
|
|
||||||
"tag": "second"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"outbounds": [],
|
|
||||||
"route": {
|
|
||||||
"rules": [
|
|
||||||
{
|
|
||||||
"inbound": "main",
|
|
||||||
"outbound": "main"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"inbound": "second",
|
|
||||||
"outbound": "second"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"auto_detect_interface": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
{
|
|
||||||
"outbounds": [
|
|
||||||
{
|
|
||||||
"type": "vless",
|
|
||||||
"server": "$HOST",
|
|
||||||
"server_port": "$PORT",
|
|
||||||
"uuid": "$UUID",
|
|
||||||
"flow": "xtls-rprx-vision",
|
|
||||||
"tls": {
|
|
||||||
"enabled": true,
|
|
||||||
"insecure": false,
|
|
||||||
"server_name": "$FAKE_SERVER",
|
|
||||||
"utls": {
|
|
||||||
"enabled": true,
|
|
||||||
"fingerprint": "chrome"
|
|
||||||
},
|
|
||||||
"reality": {
|
|
||||||
"enabled": true,
|
|
||||||
"public_key": "$PUBLIC_KEY",
|
|
||||||
"short_id": "$SHORT_ID"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"tag": "$TAG"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
{
|
|
||||||
"log": {
|
|
||||||
"level": "warn"
|
|
||||||
},
|
|
||||||
"inbounds": [
|
|
||||||
{
|
|
||||||
"type": "tproxy",
|
|
||||||
"listen": "::",
|
|
||||||
"listen_port": 1602,
|
|
||||||
"sniff": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"outbounds": [
|
|
||||||
{
|
|
||||||
"type": "vless",
|
|
||||||
"server": "$HOST",
|
|
||||||
"server_port": "$PORT",
|
|
||||||
"uuid": "$UUID",
|
|
||||||
"flow": "xtls-rprx-vision",
|
|
||||||
"tls": {
|
|
||||||
"enabled": true,
|
|
||||||
"insecure": false,
|
|
||||||
"server_name": "$FAKE_SERVER",
|
|
||||||
"utls": {
|
|
||||||
"enabled": true,
|
|
||||||
"fingerprint": "chrome"
|
|
||||||
},
|
|
||||||
"reality": {
|
|
||||||
"enabled": true,
|
|
||||||
"public_key": "$PUBLIC_KEY",
|
|
||||||
"short_id": "$SHORT_ID"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"route": {
|
|
||||||
"auto_detect_interface": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user