Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

改正openwrt上bind網路卡的行為 #1803

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 132 additions & 9 deletions package/openwrt/files/etc/init.d/smartdns
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

START=19
STOP=82
NAME=smartdns
Expand Down Expand Up @@ -514,6 +513,44 @@ conf_append_bind()
done
}

conf_append_bind_interface()
{
local bind_type="$1"
local port="$2"
local interfaces="$3"
local ipv6_server="$4"
local ARGS="$5"
local intf=""

for intf in ${interfaces}; do
local __device
local __addrs
network_get_device __device $intf
[ -z "$__device" ] && continue

if [ "$ipv6_server" = "1" ]; then
local __addr
__addr=$(ifconfig "$__device"|grep 'Scope:Link' \
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ifconfig命令应该要替换为ip命令,ifconfig大部分系统默认不安装

Copy link
Author

@hizukiayaka hizukiayaka Aug 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

您原本的script中主要是使用ifconfig的,ip是ip route2或者busybox中的tiny版本。
所以這樣的考量依舊使用了ifconfig,您確認一下如果要ip-addresss(8)我就改了。

| sed 's:.*\(fe[8ab].*\)/.*:\1:')

[ -n "${__addr}" ] || break

conf_append "$bind_type" "[${__addr}]:${port}@${__device} $ARGS"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里还有一个场景是,动态增加的IP,可能就会导致问题。
目前smartdns并不会监听ip地址变化。

如果网口新增了IP,那么新增的将会无法提供服务。

感觉应该设计为两种模式:

  1. 绑定网口模式。
  2. 绑定IP地址模式。

不应该两种一起使用

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

這個唯獨有問題的場景是下發ipv6位置到lan這邊來,但是一般dhcp會在上面那個link local上在回應client的request。
當然這邊不是沒有考慮過這個問題,hotplug.d可以install一個hook去call update file。
bind port沒有辦法bind到某個interface上而不衝突。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

不是不是 考虑pppoe重新拨号的情况。。。而且有些openwrt固件重新拨号不会触发hotplug

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

應該沒有人去bind 到 wan這邊吧。沒有invoke hotplug那就是非offical行為了, script這個level是沒法解決的。
非要解決只能去register個netlink來hook event 了。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ipv6有一个情形是上游宣告新的ip后,没有宣告旧ip失效,导致设备上存在多个ip

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK,我要確認一下PD的規範和dnsmasq的行為。
這個問題要不要加一個option只bind 到ULA和link local先完善這個部分feature

Copy link
Contributor

@PikuZheng PikuZheng Aug 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dnsmasq有一个选项是“非全部地址(动态绑定到接口而不是通配符地址(建议作为 linux 的默认值)”。但是不知道它对接口ip变化是怎么处理的
这个有提议 #1718 #1793 看看能不能先解决这两个情形
我说的ipv6那个场景有点特殊但挺常见。比如pppoe重拨了,ra会下发一个新的ipv6段,但旧的又没过期。这个情形下设备上就会有多个ipv6公网地址,而且windows和android都能正确处理。但是对于openwrt似乎会有问题。另一方面如果内网用ipv6作为dns服务器,我建议自己起一个私有ipv6段用。

Copy link
Author

@hizukiayaka hizukiayaka Aug 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#1718 這次的commit可以解決這個問題
#1793 的方案是不對的,會和其他dhcp server如dnsmasq造成conflict。udp 沒有connect()是不保證會是同一個process 來response的。
dnsmasq的--listen-address, --bind-interfaces, --interface這幾個options其實一直造成我很困擾,
listen-address不管dhcp的,因為dhcp是工作在broadcast address,但是bind-interfaces 會造成dhcp用的port conflict。
而--interface郵會造成比如我只要dhcp service而不要dns service的場景出問題。
這邊我是計畫向dnsmasq提issue來address這個場景。
不過對於smartdns本身應該這些commits是可以避免自己造成bug的。
所以這個部分建議先接受我這樣的方案,後面再改善。


network_get_ipaddrs6 __addrs "$intf"
for __addr in ${__addrs}; do
[ -n "${__addr}" ] && \
conf_append "$bind_type" "[${__addr}]:${port}@${__device} $ARGS"
done
fi

network_get_ipaddrs __addrs "$intf"
for __addr in ${__addrs}; do
conf_append "$bind_type" "[${__addr}]:${port}@${__device} $ARGS"
done
done
}

load_second_server()
{
local section="$1"
Expand Down Expand Up @@ -579,6 +616,79 @@ load_second_server()
[ "$seconddns_tcp_server" = "1" ] && conf_append_bind "bind-tcp" "$seconddns_port" "$device" "$ipv6_server" "$ARGS"
}

load_second_service()
{
local section="$1"
local server_flags=""
local ADDR=""
local device=""

config_get_bool enabled "$section" "enabled" "0"
[ "$enabled" = "0" ] && return

config_get port "$section" "port" "6553"

config_get_bool no_speed_check "$section" "no_speed_check" "0"
[ "$no_speed_check" = "1" ] && server_flags="$server_flags -no-speed-check"

config_get server_group "$section" "server_group" ""
[ -z "$server_group" ] || server_flags="$server_flags -group $server_group"

config_get_bool no_rule_addr "$section" "no_rule_addr" "0"
[ "$no_rule_addr" = "1" ] && server_flags="$server_flags -no-rule-addr"

config_get_bool no_rule_nameserver "$section" "no_rule_nameserver" "0"
[ "$no_rule_nameserver" = "1" ] && server_flags="$server_flags -no-rule-nameserver"

config_get_bool no_rule_ipset "$section" "no_rule_ipset" "0"
[ "$no_rule_ipset" = "1" ] && server_flags="$server_flags -no-rule-ipset"

config_get_bool no_rule_soa "$section" "no_rule_soa" "0"
[ "$no_rule_soa" = "1" ] && server_flags="$server_flags -no-rule-soa"

config_get_bool no_dualstack_selection "$section" "no_dualstack_selection" "0"
[ "$no_dualstack_selection" = "1" ] && server_flags="$server_flags -no-dualstack-selection"

config_get_bool no_cache "$section" "no_cache" "0"
[ "$no_cache" = "1" ] && server_flags="$server_flags -no-cache"

config_get_bool force_aaaa_soa "$section" "force_aaaa_soa" "0"
[ "$force_aaaa_soa" = "1" ] && server_flags="$server_flags -force-aaaa-soa"

config_get_bool force_https_soa "$section" "force_https_soa" "0"
[ "$force_https_soa" = "1" ] && server_flags="$server_flags -force-https-soa"

config_get_bool no_ip_alias "$section" "no_ip_alias" "0"
[ "$no_ip_alias" = "1" ] && server_flags="$server_flags -no-ip-alias"

config_get ipset_name "$section" "ipset_name" ""
[ -z "$ipset_name" ] || server_flags="$server_flags -ipset $ipset_name"

config_get nftset_name "$section" "nftset_name" ""
[ -z "$nftset_name" ] || server_flags="$server_flags -nftset $nftset_name"

config_get_bool bind_device "$section" "bind_device" "0"
config_get bind_device_name "$section" "bind_device_name" "${lan_device}"
[ ! -z "$bind_device_name" ] && [ "$bind_device" = "1" ] && device="${bind_device_name}"
config_get bind_interfaces "$section" "bind_interface" ""

config_get_bool "tcp_server" "$section" "tcp_server" "1"
config_get ipv6_server "$section" "ipv6_server" "1"

config_get server_flags "$section" "server_flags" ""
[ -z "$server_flags" ] || server_flags="$server_flags $server_flags"
local __conf_bind_func
if [ ! -z $bind_interfaces ]; then
__conf_bind_func="conf_append_bind_interface"
device=${bind_interfaces}
else
__conf_bind_func="conf_append_bind"
fi

$__conf_bind_func "bind" "$port" "$device" "$ipv6_server" "$server_flags"
[ "$tcp_server" = "1" ] && $__conf_bind_func "bind-tcp" "$port" "$device" "$ipv6_server" "$server_flags"
}

conf_append_conf_files()
{
local conf_file="$1"
Expand Down Expand Up @@ -655,7 +765,7 @@ load_service()
[ ! -z "$speed_check_mode" ] && conf_append "speed-check-mode" "$speed_check_mode"

config_get dualstack_ip_selection "$section" "dualstack_ip_selection" "0"
[ "$dualstack_ip_selection" = "0" ] && conf_append "dualstack-ip-selection" "no"
[ "$dualstack_ip_selection" = "0" ] && server_flags="$server_flags -no-dualstack-selection"

config_get prefetch_domain "$section" "prefetch_domain" "0"
[ "$prefetch_domain" = "1" ] && conf_append "prefetch-domain" "yes"
Expand All @@ -670,10 +780,10 @@ load_service()
[ "$resolve_local_hostnames" = "1" ] && conf_append "dnsmasq-lease-file" "$dnsmasq_lease_file"

config_get force_aaaa_soa "$section" "force_aaaa_soa" "0"
[ "$force_aaaa_soa" = "1" ] && qtype_soa_list="$qtype_soa_list 28"
[ "$force_aaaa_soa" = "1" ] && server_flags="$server_flags -force-aaaa-soa"

config_get force_https_soa "$section" "force_https_soa" "1"
[ "$force_https_soa" = "1" ] && qtype_soa_list="$qtype_soa_list 65"
config_get force_https_soa "$section" "force_https_soa" "0"
[ "$force_https_soa" = "1" ] && server_flags="$server_flags -force-https-soa"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里修改的原因是什么?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

預設數值不要關閉對IPv6的查詢。
另外force-qtype-SOA 是一個全局的option,我爲了免得apply到每個interface的不同設定中去。
現在就算是main server也是被認爲獨立的,所以應該要這樣改。


config_get auto_set_dnsmasq "$section" "auto_set_dnsmasq" "1"

Expand Down Expand Up @@ -739,6 +849,7 @@ load_service()

config_get_bool bind_device "$section" "bind_device" "0"
config_get bind_device_name "$section" "bind_device_name" "${lan_device}"
config_get bind_interfaces "$section" "bind_interface" ""
[ ! -z "$bind_device_name" ] && [ "$bind_device" = "1" ] && device="${bind_device_name}"

config_get cache_file "$section" "cache_file" "$SMARTDNS_CONF_DIR/smartdns.cache"
Expand Down Expand Up @@ -829,16 +940,25 @@ load_service()
[ "$auto_set_dnsmasq" = "0" ] && [ "$old_auto_set_dnsmasq" = "1" ] && stop_forward_dnsmasq "$old_port" "0"
}

conf_append_bind "bind" "$port" "$device" "$ipv6_server" "$server_flags"
[ "$tcp_server" = "1" ] && conf_append_bind "bind-tcp" "$port" "$device" "$ipv6_server" "$server_flags"
[ "$tls_server" = "1" ] && conf_append_bind "bind-tls" "$tls_server_port" "$device" "$ipv6_server" "$server_flags"
[ "$doh_server" = "1" ] && conf_append_bind "bind-https" "$doh_server_port" "$device" "$ipv6_server" "$server_flags"
local __conf_bind_func
if [ ! -z $bind_interfaces ]; then
__conf_bind_func="conf_append_bind_interface"
device=${bind_interfaces}
else
__conf_bind_func="conf_append_bind"
fi

$__conf_bind_func "bind" "$port" "$device" "$ipv6_server" "$server_flags"
[ "$tcp_server" = "1" ] && $__conf_bind_func "bind-tcp" "$port" "$device" "$ipv6_server" "$server_flags"
[ "$tls_server" = "1" ] && $__conf_bind_func "bind-tls" "$tls_server_port" "$device" "$ipv6_server" "$server_flags"
[ "$doh_server" = "1" ] && $__conf_bind_func "bind-https" "$doh_server_port" "$device" "$ipv6_server" "$server_flags"

[ ! -z "$bind_cert" ] && conf_append "bind-cert-file" "$bind_cert"
[ ! -z "$bind_cert_key" ] && conf_append "bind-cert-key-file" "$bind_cert_key"
[ ! -z "$bind_cert_key_pass" ] && conf_append "bind-cert-key-pass" "$bind_cert_key_pass"

load_second_server "$section"
config_foreach load_second_service "service"

config_foreach load_server "server"

Expand Down Expand Up @@ -996,6 +1116,9 @@ start_service()
{
check_and_add_entry
config_load "smartdns"

. /lib/functions/network.sh

config_foreach load_service "smartdns"
}

Expand Down
Loading