2025-07-18 00:58:03 +08:00

696 lines
27 KiB
Bash

#!/bin/sh
. /usr/share/openclash/ruby.sh
. /usr/share/openclash/log.sh
. /lib/functions.sh
LOG_FILE="/tmp/openclash.log"
CONFIG_FILE="$5"
config_load openclash
config_get custom_fakeip_filter "config" "custom_fakeip_filter" 0
config_get custom_name_policy "config" "custom_name_policy" 0
config_get custom_host "config" "custom_host" 0
config_get enable_custom_dns "config" "enable_custom_dns" 0
config_get append_wan_dns "config" "append_wan_dns" 0
config_get custom_fallback_filter "config" "custom_fallback_filter" 0
config_get china_ip_route "config" "china_ip_route" 0
config_get china_ip6_route "config" "china_ip6_route" 0
config_get enable_redirect_dns "config" "enable_redirect_dns" 1
[ "$china_ip_route" -ne 0 ] && [ "$china_ip_route" -ne 1 ] && [ "$china_ip_route" -ne 2 ] && china_ip_route=0
[ "$china_ip6_route" -ne 0 ] && [ "$china_ip6_route" -ne 1 ] && [ "$china_ip6_route" -ne 2 ] && china_ip6_route=0
en_mode_tun=${11:-0}
if [ -z "${12}" ]; then
stack_type=${31:-"system"}
else
stack_type=${12}
fi
if [ "$1" = "fake-ip" ] && [ "$enable_redirect_dns" != "2" ]; then
TMP_FILTER_FILE="/tmp/yaml_openclash_fake_filter_include"
> "$TMP_FILTER_FILE"
process_pass_list() {
[ ! -f "$1" ] && return
awk '
!/^$/ && !/^#/ {
if ($0 ~ /^\+?\./ || $0 ~ /^\*\./) {
print $0
} else {
print "+."$0
}
}
' "$1" >> "$TMP_FILTER_FILE" 2>/dev/null
}
if [ "$china_ip_route" != "0" ]; then
process_pass_list "/etc/openclash/custom/openclash_custom_chnroute_pass.list"
fi
if [ "$china_ip6_route" != "0" ]; then
process_pass_list "/etc/openclash/custom/openclash_custom_chnroute6_pass.list"
fi
fi
# 获取认证信息
yml_auth_get()
{
local section="$1"
local enabled username password
config_get_bool "enabled" "$section" "enabled" "1"
config_get "username" "$section" "username" ""
config_get "password" "$section" "password" ""
if [ "$enabled" = "0" ]; then
return
fi
if [ -z "$username" ] || [ -z "$password" ]; then
return
else
LOG_OUT "Tip: You have seted the authentication of SOCKS5/HTTP(S) proxy with【$username:$password】..."
echo " - $username:$password" >>/tmp/yaml_openclash_auth
fi
}
# 添加自定义DNS设置
yml_dns_custom()
{
if [ "$1" = 1 ] || [ "$3" = 1 ]; then
sys_dns_append "$3" "$4"
config_load "openclash"
config_foreach yml_dns_get "dns_servers" "$2"
fi
}
# 获取DHCP或接口的DNS并追加
sys_dns_append()
{
if [ "$1" = 1 ]; then
wan_dns=$(/usr/share/openclash/openclash_get_network.lua "dns")
wan6_dns=$(/usr/share/openclash/openclash_get_network.lua "dns6")
wan_gate=$(/usr/share/openclash/openclash_get_network.lua "gateway")
wan6_gate=$(/usr/share/openclash/openclash_get_network.lua "gateway6")
dhcp_iface=$(/usr/share/openclash/openclash_get_network.lua "dhcp")
pppoe_iface=$(/usr/share/openclash/openclash_get_network.lua "pppoe")
if [ -z "$dhcp_iface" ] && [ -z "$pppoe_iface" ]; then
if [ -n "$wan_dns" ]; then
for i in $wan_dns; do
echo " - \"$i\"" >>/tmp/yaml_config.namedns.yaml
done
fi
if [ -n "$wan6_dns" ] && [ "$2" = 1 ]; then
for i in $wan6_dns; do
echo " - \"[${i}]:53\"" >>/tmp/yaml_config.namedns.yaml
done
fi
if [ -n "$wan_gate" ]; then
for i in $wan_gate; do
echo " - \"$i\"" >>/tmp/yaml_config.namedns.yaml
done
fi
if [ -n "$wan6_gate" ] && [ "$2" = 1 ]; then
for i in $wan6_gate; do
echo " - \"[${i}]:53\"" >>/tmp/yaml_config.namedns.yaml
done
fi
else
if [ -n "$dhcp_iface" ]; then
for i in $dhcp_iface; do
echo " - dhcp://\"$i\"" >>/tmp/yaml_config.namedns.yaml
done
if [ -n "$wan_gate" ]; then
for i in $wan_gate; do
echo " - \"$i\"" >>/tmp/yaml_config.namedns.yaml
done
fi
if [ -n "$wan6_gate" ] && [ "$2" = 1 ]; then
for i in $wan6_gate; do
echo " - \"[${i}]:53\"" >>/tmp/yaml_config.namedns.yaml
done
fi
fi
if [ -n "$pppoe_iface" ]; then
if [ -n "$wan_dns" ]; then
for i in $wan_dns; do
echo " - \"$i\"" >>/tmp/yaml_config.namedns.yaml
done
fi
if [ -n "$wan6_dns" ] && [ "$2" = 1 ]; then
for i in $wan6_dns; do
echo " - \"[${i}]:53\"" >>/tmp/yaml_config.namedns.yaml
done
fi
fi
fi
if [ -f "/tmp/yaml_config.namedns.yaml" ] && [ -z "$(grep "^ \{0,\}nameserver:$" /tmp/yaml_config.namedns.yaml 2>/dev/null)" ]; then
sed -i '1i\ nameserver:' "/tmp/yaml_config.namedns.yaml"
fi
fi
}
PROXY_GROUPS=$(ruby -ryaml -rYAML -I "/usr/share/openclash" -E UTF-8 -e "
begin
Value = YAML.load_file('$CONFIG_FILE')
if Value.key?('proxy-groups') && Value['proxy-groups'].is_a?(Array)
Value['proxy-groups'].each { |x| puts x['name'] if x.key?('name') }
end
rescue Exception => e
YAML.LOG('Error: proxy-groups Get Failed,【%s】' % [e.message])
end
" 2>/dev/null)
yml_dns_get()
{
local section="$1" regex='^([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}$'
local enabled port type ip group dns_type dns_address interface specific_group node_resolve http3 ecs_subnet ecs_override
config_get_bool "enabled" "$section" "enabled" "1"
[ "$enabled" = "0" ] && return
config_get "ip" "$section" "ip" ""
[ -z "$ip" ] && return
config_get "port" "$section" "port" ""
config_get "type" "$section" "type" ""
config_get "group" "$section" "group" ""
config_get "interface" "$section" "interface" ""
config_get "specific_group" "$section" "specific_group" ""
config_get_bool "node_resolve" "$section" "node_resolve" "0"
config_get_bool "direct_nameserver" "$section" "direct_nameserver" "0"
config_get_bool "http3" "$section" "http3" "0"
config_get_bool "skip_cert_verify" "$section" "skip_cert_verify" "0"
config_get_bool "ecs_override" "$section" "ecs_override" "0"
config_get "ecs_subnet" "$section" "ecs_subnet" ""
config_get "disable_ipv4" "$section" "disable_ipv4" "0"
config_get "disable_ipv6" "$section" "disable_ipv6" "0"
if [[ "$ip" =~ "$regex" ]] || [ -n "$(echo "${ip}" | grep -Eo "${regex}")" ]; then
ip="[${ip}]"
fi
case "$type" in
"tcp") dns_type="tcp://" ;;
"tls") dns_type="tls://" ;;
"udp") dns_type="" ;;
"https") dns_type="https://" ;;
"quic") dns_type="quic://" ;;
*) dns_type="" ;;
esac
if [ -n "$port" ]; then
if [ "${ip%%/*}" != "${ip#*/}" ]; then
dns_address="${ip%%/*}:$port/${ip#*/}"
else
dns_address="$ip:$port"
fi
else
dns_address="$ip"
fi
if [ "$specific_group" != "Disable" ] && [ -n "$specific_group" ]; then
group_check=$(echo "$PROXY_GROUPS" | grep -F -w -m 1 "$specific_group")
[ -n "$group_check" ] && specific_group_param="$group_check" || specific_group_param=""
else
specific_group_param=""
fi
[ "$interface" != "Disable" ] && [ -n "$interface" ] && interface_param="$interface" || interface_param=""
[ "$http3" = "1" ] && http3_param="h3=true" || http3_param=""
[ "$skip_cert_verify" = "1" ] && skip_cert_verify_param="skip-cert-verify=true" || skip_cert_verify_param=""
[ -n "$ecs_subnet" ] && ecs_subnet_param="ecs=$ecs_subnet" || ecs_subnet_param=""
[ "$ecs_override" = "1" ] && [ -n "$ecs_subnet_param" ] && ecs_override_param="ecs-override=true" || ecs_override_param=""
[ "$disable_ipv4" = "1" ] && disable_ipv4_param="disable-ipv4=true" || disable_ipv4_param=""
[ "$disable_ipv6" = "1" ] && disable_ipv6_param="disable-ipv6=true" || disable_ipv6_param=""
params=""
append_param() {
if [ -n "$1" ]; then
[ -z "$params" ] && params="#" || params="$params&"
params="$params$1"
fi
}
append_param "$specific_group_param"
append_param "$interface_param"
append_param "$http3_param"
append_param "$skip_cert_verify_param"
append_param "$ecs_subnet_param"
append_param "$ecs_override_param"
append_param "$disable_ipv4_param"
append_param "$disable_ipv6_param"
full_dns_address="$dns_type$dns_address$params"
if [ "$node_resolve" = "1" ]; then
if ! grep -q "^ \{0,\}proxy-server-nameserver:$" /tmp/yaml_config.proxynamedns.yaml 2>/dev/null; then
echo " proxy-server-nameserver:" >/tmp/yaml_config.proxynamedns.yaml
fi
echo " - \"$full_dns_address\"" >>/tmp/yaml_config.proxynamedns.yaml
fi
if [ "$direct_nameserver" = "1" ]; then
if ! grep -q "^ \{0,\}direct-nameserver:$" /tmp/yaml_config.directnamedns.yaml 2>/dev/null; then
echo " direct-nameserver:" >/tmp/yaml_config.directnamedns.yaml
fi
echo " - \"$full_dns_address\"" >>/tmp/yaml_config.directnamedns.yaml
fi
case "$group" in
"nameserver")
if ! grep -q "^ \{0,\}nameserver:$" /tmp/yaml_config.namedns.yaml 2>/dev/null; then
echo " nameserver:" >/tmp/yaml_config.namedns.yaml
fi
echo " - \"$full_dns_address\"" >>/tmp/yaml_config.namedns.yaml
;;
"fallback")
if ! grep -q "^ \{0,\}fallback:$" /tmp/yaml_config.falldns.yaml 2>/dev/null; then
echo " fallback:" >/tmp/yaml_config.falldns.yaml
fi
echo " - \"$full_dns_address\"" >>/tmp/yaml_config.falldns.yaml
;;
"default")
if ! grep -q "^ \{0,\}default-nameserver:$" /tmp/yaml_config.defaultdns.yaml 2>/dev/null; then
echo " default-nameserver:" >/tmp/yaml_config.defaultdns.yaml
fi
echo " - \"$full_dns_address\"" >>/tmp/yaml_config.defaultdns.yaml
;;
esac
}
config_foreach yml_auth_get "authentication"
yml_dns_custom "$enable_custom_dns" "$5" "$append_wan_dns" "${16}"
ruby -ryaml -rYAML -I "/usr/share/openclash" -E UTF-8 -e "
def safe_load_yaml(file_path)
return nil unless File.exist?(file_path)
YAML.load_file(file_path)
rescue
nil
end
def merge_list_from_file(dns_hash, key, file_path)
return unless File.exist?(file_path)
lines = File.readlines(file_path).map { |l| l.gsub(/#.*$/, '').strip }.reject(&:empty?)
return if lines.empty?
(dns_hash[key] ||= []).concat(lines).uniq!
end
begin
config_file = '$5'
Value = YAML.load_file(config_file)
rescue Exception => e
YAML.LOG('Error: Load File Failed,【%s】' % [e.message])
exit
end
fake_ip_mode = '$1'
secret = '$2'
controller_port = '$3'
redir_port = '$4'
enable_ipv6 = '$6' == '1'
http_port = '$7'
socks_port = '$8'
log_level = '$9'
mode = '${10}'
en_mode_tun = '$en_mode_tun'
stack_type = '$stack_type'
dns_listen_port = '${13}'
mixed_port = '${14}'
tproxy_port = '${15}'
dns_ipv6 = '${16}' == '1'
store_fake_ip = '${17}' == '1'
enable_sniffer = '${18}' == '1'
geodata_mode = '${19}' == '1'
geodata_loader = '${20}'
append_sniffer_config = '${21}' == '1'
interface_name = '${22}'
tcp_concurrent = '${23}' == '1'
add_default_from_dns = '${25}' == '1'
sniffer_parse_pure_ip = '${26}' == '1'
find_process_mode = '${27}'
fake_ip_range = '${28}'
global_client_fingerprint = '${29}'
tun_device_setting = '${30}'
unified_delay = '${32}' == '1'
respect_rules = '${33}' == '1'
fake_ip_filter_mode = '${34}'
routing_mark_setting = '${35}'
quic_gso = '${36}' == '1'
cors_origin = '${37}'
geo_custom_url = '${38}'
geoip_custom_url = '${39}'
geosite_custom_url = '${40}'
geoasn_custom_url = '${41}'
enable_custom_dns = '$enable_custom_dns' == '1'
append_wan_dns = '$append_wan_dns' == '1'
custom_fakeip_filter = '$custom_fakeip_filter' == '1'
china_ip_route = '$china_ip_route' != '0'
china_ip6_route = '$china_ip6_route' != '0'
custom_name_policy = '$custom_name_policy' == '1'
custom_host = '$custom_host' == '1'
enable_redirect_dns = '$enable_redirect_dns'
Value['dns'] ||= {}
threads = []
threads << Thread.new do
begin
Value['redir-port'] = redir_port.to_i
Value['tproxy-port'] = tproxy_port.to_i
Value['port'] = http_port.to_i
Value['socks-port'] = socks_port.to_i
Value['mixed-port'] = mixed_port.to_i
Value['mode'] = mode
Value['log-level'] = log_level if log_level != '0'
Value['allow-lan'] = true
Value['external-controller'] = '0.0.0.0:' + controller_port
Value['secret'] = secret
Value['bind-address'] = '*'
Value['external-ui'] = '/usr/share/openclash/ui'
Value['external-ui-name'] = 'metacubexd'
Value.delete('external-ui-url')
if !Value.key?('keep-alive-interval') && !Value.key?('keep-alive-idle')
Value['keep-alive-interval'] = 15
Value['keep-alive-idle'] = 600
end
Value['ipv6'] = enable_ipv6
Value['interface-name'] = interface_name if interface_name != '0'
Value['geodata-mode'] = true if geodata_mode
Value['geodata-loader'] = geodata_loader if geodata_loader != '0'
Value['tcp-concurrent'] = true if tcp_concurrent
Value['unified-delay'] = true if unified_delay
Value['find-process-mode'] = find_process_mode if find_process_mode != '0'
Value['global-client-fingerprint'] = global_client_fingerprint if global_client_fingerprint != '0'
(Value['experimental'] ||= {})['quic-go-disable-gso'] = true if quic_gso
if cors_origin != '0'
(Value['external-controller-cors'] ||= {})['allow-origins'] = [cors_origin]
Value['external-controller-cors']['allow-private-network'] = true
end
Value['geox-url'] ||= {}
if geo_custom_url != '0'
Value['geox-url']['mmdb'] = geo_custom_url
end
if geoip_custom_url != '0'
Value['geox-url']['geoip'] = geoip_custom_url
end
if geosite_custom_url != '0'
Value['geox-url']['geosite'] = geosite_custom_url
end
if geoasn_custom_url != '0'
Value['geox-url']['asn'] = geoasn_custom_url
end
Value['dns']['enable'] = true
Value['dns']['ipv6'] = dns_ipv6
Value['ipv6'] = true if dns_ipv6
if fake_ip_mode == 'redir-host'
Value['dns']['enhanced-mode'] = 'redir-host'
Value['dns'].delete('fake-ip-range')
else
Value['dns']['enhanced-mode'] = 'fake-ip'
Value['dns']['fake-ip-range'] = fake_ip_range
end
Value['dns']['listen'] = '0.0.0.0:' + dns_listen_port
Value['dns']['respect-rules'] = true if respect_rules
if enable_sniffer
sniffer_config = {
'enable' => true, 'override-destination' => true,
'sniff' => {'QUIC' => {'ports' => [443]}, 'TLS' => {'ports' => [443, 8443]}, 'HTTP' => {'ports' => [80, '8080-8880'], 'override-destination' => true}},
'force-domain' => ['+.netflix.com', '+.nflxvideo.net', '+.amazonaws.com', '+.media.dssott.com'],
'skip-domain' => ['+.apple.com', 'Mijia Cloud', 'dlg.io.mi.com', '+.oray.com', '+.sunlogin.net', '+.push.apple.com']
}
sniffer_config['force-dns-mapping'] = true if fake_ip_mode == 'redir-host'
sniffer_config['parse-pure-ip'] = true if sniffer_parse_pure_ip
Value['sniffer'] = sniffer_config
if append_sniffer_config && (custom_sniffer = safe_load_yaml('/etc/openclash/custom/openclash_custom_sniffer.yaml'))
Value['sniffer'].merge!(custom_sniffer['sniffer']) if custom_sniffer && custom_sniffer['sniffer']
end
end
if en_mode_tun != '0' || ['2', '3'].include?(tun_device_setting)
Value['tun'] = {
'enable' => true, 'stack' => stack_type, 'device' => 'utun',
'dns-hijack' => ['127.0.0.1:53'], 'endpoint-independent-nat' => true,
'auto-route' => false, 'auto-detect-interface' => false,
'auto-redirect' => false, 'strict-route' => false
}
Value['tun'].delete('iproute2-table-index')
else
Value.delete('tun')
end
Value.delete('iptables')
(Value['profile'] ||= {})['store-selected'] = true
Value['profile']['store-fake-ip'] = true if store_fake_ip
Value.delete('ebpf')
if routing_mark_setting == '0'
Value['routing-mark'] = 6666
else
Value.delete('routing-mark')
end
Value.delete('auto-redir')
rescue Exception => e
YAML.LOG('Error: Set General Failed,【%s】' % [e.message])
end
end
threads << Thread.new do
begin
if enable_custom_dns || append_wan_dns
if (namedns_config = safe_load_yaml('/tmp/yaml_config.namedns.yaml')) && namedns_config['nameserver']
if enable_custom_dns
Value['dns']['nameserver'] = namedns_config['nameserver'].uniq
elsif append_wan_dns
(Value['dns']['nameserver'] ||= []).concat(namedns_config['nameserver']).uniq!
end
if enable_custom_dns && (falldns_config = safe_load_yaml('/tmp/yaml_config.falldns.yaml')) && falldns_config['fallback']
Value['dns']['fallback'] = falldns_config['fallback'].uniq
end
elsif enable_custom_dns
YAML.LOG('Error: Nameserver Option Must Be Setted, Stop Customing DNS Servers')
end
end
rescue Exception => e
YAML.LOG('Error: Set Custom DNS Failed,【%s】' % [e.message])
end
begin
if enable_custom_dns
if (defaultdns_config = safe_load_yaml('/tmp/yaml_config.defaultdns.yaml')) && defaultdns_config['default-nameserver']
(Value['dns']['default-nameserver'] ||= []).concat(defaultdns_config['default-nameserver']).uniq!
end
end
if add_default_from_dns
reg = /^dhcp:\/\/|^system($|:\/\/)|([0-9a-zA-Z-]{1,}\.)+([a-zA-Z]{2,})/
servers_to_check = Value.dig('dns', 'nameserver').to_a | Value.dig('dns', 'fallback').to_a
non_domain_servers = servers_to_check.reject { |s| s.match?(reg) }
if non_domain_servers.any?
(Value['dns']['default-nameserver'] ||= []).concat(non_domain_servers).uniq!
end
end
rescue Exception => e
YAML.LOG('Error: Set default-nameserver Failed,【%s】' % [e.message])
end
begin
if '$custom_fallback_filter' == '1'
if !Value.dig('dns', 'fallback')
YAML.LOG('Error: Fallback-Filter Need fallback of DNS Been Setted, Ignore...')
elsif (filter_config = safe_load_yaml('/etc/openclash/custom/openclash_custom_fallback_filter.yaml'))
Value['dns']['fallback-filter'] = filter_config['fallback-filter']
else
YAML.LOG('Error: Unable To Parse Custom Fallback-Filter File, Ignore...')
end
end
rescue Exception => e
YAML.LOG('Error: Set fallback-filter Failed,【%s】' % [e.message])
end
end
threads << Thread.new do
begin
if enable_custom_dns
if (proxydns = safe_load_yaml('/tmp/yaml_config.proxynamedns.yaml')) && proxydns['proxy-server-nameserver']
(Value['dns']['proxy-server-nameserver'] ||= []).concat(proxydns['proxy-server-nameserver']).uniq!
end
end
rescue Exception => e
YAML.LOG('Error: Set proxy-server-nameserver Failed,【%s】' % [e.message])
end
begin
if enable_custom_dns
if (directdns = safe_load_yaml('/tmp/yaml_config.directnamedns.yaml')) && directdns['direct-nameserver']
(Value['dns']['direct-nameserver'] ||= []).concat(directdns['direct-nameserver']).uniq!
end
end
rescue Exception => e
YAML.LOG('Error: Set direct-nameserver Failed,【%s】' % [e.message])
end
end
# nameserver-policy
threads << Thread.new do
begin
if custom_name_policy
if (policy = safe_load_yaml('/etc/openclash/custom/openclash_custom_domain_dns_policy.list'))
(Value['dns']['nameserver-policy'] ||= {}).merge!(policy)
end
end
rescue Exception => e
YAML.LOG('Error: Set Nameserver-Policy Failed,【%s】' % [e.message])
end
end
# Fake-IP Filter
threads << Thread.new do
begin
if custom_fakeip_filter
Value['dns']['fake-ip-filter-mode'] = fake_ip_filter_mode
if fake_ip_mode == 'fake-ip'
merge_list_from_file(Value['dns'], 'fake-ip-filter', '/etc/openclash/custom/openclash_custom_fake_filter.list')
merge_list_from_file(Value['dns'], 'fake-ip-filter', '/tmp/yaml_openclash_fake_filter_include')
end
end
if fake_ip_mode == 'fake-ip' && (china_ip_route || china_ip6_route)
filter_mode = Value.dig('dns', 'fake-ip-filter-mode')
filters = Value.dig('dns', 'fake-ip-filter') || []
if filter_mode == 'blacklist' || filter_mode.nil?
unless filters.include?('geosite:cn')
(Value['dns']['fake-ip-filter'] ||= []) << 'geosite:cn'
YAML.LOG('Tip: Because Need Ensure Bypassing IP Option Work, Added The Fake-IP-Filter Rule【geosite:cn】...')
end
else
deleted_filters = filters.select { |f| f =~ /(geosite:?).*(@cn|:cn|,cn|:china)/ }
if deleted_filters.any?
Value['dns']['fake-ip-filter'] -= deleted_filters
deleted_filters.each do |f|
YAML.LOG('Tip: Because Need Ensure Bypassing IP Option Work, Deleted The Fake-IP-Filter Rule【%s】...' % [f])
end
end
end
end
rescue Exception => e
YAML.LOG('Error: Set Fake-IP-Filter Failed,【%s】' % [e.message])
end
end
# Custom Hosts
threads << Thread.new do
begin
if custom_host
if (hosts_content = safe_load_yaml('/etc/openclash/custom/openclash_custom_hosts.list')) && !hosts_content.empty?
Value['dns']['use-hosts'] = true
if hosts_content.is_a?(Hash) && hosts_content.key?('hosts')
(Value['hosts'] ||= {}).merge!(hosts_content['hosts'])
else
(Value['hosts'] ||= {}).merge!(hosts_content)
end
YAML.LOG('Warning: You May Need to Turn off The Rebinding Protection Option of Dnsmasq When Hosts Has Set a Reserved Address...')
end
end
rescue Exception => e
YAML.LOG('Error: Set Hosts Rules Failed,【%s】' % [e.message])
end
end
# Authentication
threads << Thread.new do
begin
if (auth_config = safe_load_yaml('/tmp/yaml_openclash_auth'))
(Value['authentication'] ||= []).concat(auth_config).uniq!
end
rescue Exception => e
YAML.LOG('Error: Set authentication Failed,【%s】' % [e.message])
end
end
threads.each(&:join)
begin
threads.clear
# DNS Loop Check
if enable_redirect_dns != '2'
dns_options = ['nameserver', 'fallback', 'default-nameserver', 'proxy-server-nameserver', 'nameserver-policy', 'direct-nameserver']
dns_options.each do |option|
threads << Thread.new(option) do |opt|
begin
next unless Value['dns'].key?(opt) && !Value['dns'][opt].nil?
if opt != 'nameserver-policy'
original_size = Value['dns'][opt].size
Value['dns'][opt].reject! { |v| v.to_s.match?(/^system($|:\/\/)/) }
if Value['dns'][opt].size < original_size
YAML.LOG('Tip: Option【%s】is Setted【system】as DNS Server Which May Cause DNS Loop, Already Remove It...' % [opt])
end
else
Value['dns'][opt].each do |k, v|
if v.is_a?(Array)
original_size = v.size
v.reject! { |z| z.to_s.match?(/^system($|:\/\/)/) }
if v.empty?
Value['dns'][opt].delete(k)
YAML.LOG('Tip: Option【%s - %s】is Setted【system】as DNS Server Which May Cause DNS Loop, Already Remove It...' % [opt, k])
elsif v.size < original_size
YAML.LOG('Tip: Option【%s - %s】is Setted【system】as DNS Server Which May Cause DNS Loop, Already Remove It...' % [opt, k])
end
elsif v.to_s.match?(/^system($|:\/\/)/)
Value['dns'][opt].delete(k)
YAML.LOG('Tip: Option【%s - %s】is Setted【%s】as DNS Server Which May Cause DNS Loop, Already Remove It...' % [opt, k, v.to_s])
end
end
end
rescue Exception => e
YAML.LOG('Error: DNS Loop Check,【%s】' % [e.message])
end
end
end
threads.each(&:join)
end
if Value.dig('dns', 'nameserver').to_a.empty?
YAML.LOG('Tip: Detected That The nameserver DNS Option Has No Server Set, Starting To Complete...')
Value['dns']['nameserver'] = ['114.114.114.114', '119.29.29.29', '8.8.8.8', '1.1.1.1']
Value['dns']['fallback'] ||= ['https://dns.cloudflare.com/dns-query', 'https://dns.google/dns-query']
end
# proxy-server-nameserver
local_exclude = (%x{ls -l /sys/class/net/ |awk '{print \$9}' 2>&1}.each_line.map(&:strip) + ['h3=', 'skip-cert-verify=', 'ecs=', 'ecs-override='] + ['utun', 'tailscale0', 'docker0', 'tun163', 'br-lan', 'mihomo']).uniq.join('|')
proxied_server_reg = /^[^#&]+#(?:(?:#{local_exclude})[^&]*&)*(?:(?!(?:#{local_exclude}))[^&]+)/
default_proxy_servers = ['114.114.114.114', '119.29.29.29', '8.8.8.8', '1.1.1.1']
if Value.dig('dns', 'proxy-server-nameserver').to_a.empty?
all_ns_proxied = Value.dig('dns', 'nameserver').to_a.all? { |x| x.match?(proxied_server_reg) }
if respect_rules || Value.dig('dns', 'respect-rules').to_s == 'true' || all_ns_proxied
Value['dns']['proxy-server-nameserver'] = default_proxy_servers
if all_ns_proxied
YAML.LOG('Tip: Nameserver Option Maybe All Setted The Proxy Option, Auto Set Proxy-server-nameserver Option to【114.114.114.114, 119.29.29.29, 8.8.8.8, 1.1.1.1】For Avoiding Proxies Server Resolve Loop...')
else
YAML.LOG('Tip: Respect-rules Option Need Proxy-server-nameserver Option Must Be Setted, Auto Set to【114.114.114.114, 119.29.29.29, 8.8.8.8, 1.1.1.1】')
end
end
else
all_psn_proxied = Value.dig('dns', 'proxy-server-nameserver').to_a.all? { |x| x.match?(proxied_server_reg) }
if all_psn_proxied
(Value['dns']['proxy-server-nameserver'] ||= []).concat(default_proxy_servers).uniq!
YAML.LOG('Tip: Proxy-server-nameserver Option Maybe All Setted The Proxy Option, Auto Set Proxy-server-nameserver Option to【114.114.114.114, 119.29.29.29, 8.8.8.8, 1.1.1.1】For Avoiding Proxies Server Resolve Loop...')
end
end
rescue Exception => e
YAML.LOG('Error: Config File Overwrite Failed,【%s】' % [e.message])
ensure
File.open(config_file, 'w') { |f| YAML.dump(Value, f) }
end
" 2>/dev/null >> $LOG_FILE