节点重启网络Flannel Pod IP不通排查记录

问题现场

自己的实验集群,使用的k3s v1.25.7+k3s1, 网络使用的默认flannel vxlan模式。

NAME          STATUS   ROLES                  AGE    VERSION
whoops-home   Ready    <none>                 253d   v1.25.7+k3s1
whoops-k3s    Ready    control-plane,master   268d   v1.25.7+k3s1

节点whoops-k3s是CentOS7.9,折腾网络,改了ifcfg-eth0配置,systemctl restart network重启网络,一开始没发现,第二天发现nginx到集群的访问504。

这个小集群是在家里NAS和软路由上跑的,whoops-home上有一个内网穿透了的nginx,集群流量都经过这个nginx转进来走traefik ingress controller。

链路大概这样:

域名流量->nginx(whoops-home)->traefik(nodeport)->pod

Nginx报504,那就是Nginx到traefik不通,现在nginx在whoops-home上,traefik在whoops-k3s上,查了下发现从whoops-home上ping不通whoops-k3s上的Pod,但是从whoops-k3s可以ping通whoops-home上的pod。

whoops-k3s上的flannel vxlan因为重启网络挂了?

原因分析

先来看看netfilter的FORWARD,没问题

iptables -t filter -nvL | grep FORWARD
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)

看看路由, 也没问题,whoops-k3s是10.42.0.0/24网段,whoops-home是10.42.1.0/24网段。

default via 192.168.31.1 dev eth0
10.42.0.0/24 dev cni0 proto kernel scope link src 10.42.0.1
10.42.1.0/24 via 10.42.1.0 dev flannel.1 onlink
...

看看fdb? 不应该啊,whoops-k3s都能ping通whoops-home上的pod,arp要是有问题,咋ping出去的包,一看果然没问题。

sudo bridge fdb show | grep flannel.1
# 192.168.31.166 是 whoops-home
d6:f8:ec:13:3c:07 dev flannel.1 dst 192.168.31.166 self permanent

vxlan是走的flannel.1设备,这个设备是flanneld创建的,重启网络影响它了?但是如果配置不对,flanneld是不是应该自己感知调整回去呢?重启下k3s试试。

systemctl restart k3s

好了!重启k3s/flanneld,因为重配了flannel.1? 复现一下,特意检查flannel.1,网段配置、路由、arp、设备状态重启前后都没问题,重配重不配flannel.1应该不影响的啊,而且个人认为flanneld不应该这么不健壮,节点重启下network,整个节点的pod网络都挂掉了。

flannel.1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450
        inet 10.42.0.0  netmask 255.255.255.255  broadcast 0.0.0.0
        inet6 fe80::b45b:f1ff:fe24:82e4  prefixlen 64  scopeid 0x20<link>
        ether b6:5b:f1:24:82:e4  txqueuelen 0  (Ethernet)
        RX packets 237089  bytes 37524217 (35.7 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 174244  bytes 32444345 (30.9 MiB)
        TX errors 29  dropped 5 overruns 0  carrier 29  collisions 0

抓包!

tcpdump -i flannel.1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on flannel.1, link-type EN10MB (Ethernet), capture size 262144 bytes
22:28:45.852513 IP 10.42.1.0 > 10.42.0.210: ICMP echo request, id 12, seq 48, length 64
22:28:46.872698 IP 10.42.1.0 > 10.42.0.210: ICMP echo request, id 12, seq 49, length 64
22:28:47.896618 IP 10.42.1.0 > 10.42.0.210: ICMP echo request, id 12, seq 50, length 64
22:28:49.851093 IP 10.42.1.0 > 10.42.0.210: ICMP echo request, id 13, seq 1, length 64
22:28:50.872665 IP 10.42.1.0 > 10.42.0.210: ICMP echo request, id 13, seq 2, length 64
22:28:51.896473 IP 10.42.1.0 > 10.42.0.210: ICMP echo request, id 13, seq 3, length 64

从whoops-home上的ping包到flannel.1了,但是没给到Pod网卡,丢哪了?重启网络操作到底干了啥?真的要研究kernel怎么实现的vxlan了么?debug flannel.1设备?

network.service

直接看/etc/rc.d/init.d/network脚本,看看重启网络做了哪些操作。

start)
    apply_sysctl
...
stop)
   sysctl -w net.ipv4.ip_forward=0 > /dev/null 2>&1
...
restart|force-reload)
    cd "$CWD"
    $0 stop
    $0 start
...

好嘛,stop时候关了net.ipv4.ip_forward,flannel.1当然不把包往pod的网卡转了,重启k3s/flanneld,flanneld动态又把参数改回来了,所以就通了,复现验证一下,还真是。
搞不懂network.service stop为啥关这个,但是start时候也应该把之前的参数还回来吧?对不起,没有持久化的sysctl在start的apply_sysctl里还不回来。

修复搞定

echo net.ipv4.ip_forward=1 >> /etc/sysctl.conf

验证一下,重启网络不影响Pod网络联通性了!

总结

之前特意研究了下flannel的vxlan模式,这次遇这么个case,又深刻了~

阅读全文

Linux Network配置及工作原理

Linux Network不同发行版配置方法不同,管理工具纷繁复杂,即使是同一种发行版不同版本管理工具也不断变化。作为系统管理员,环境里可能有各种版本的系统,所以要理一理关于Network的配置思路。

发行版配置工具

  • Centos6 使用 network.service。
  • Centos7 network.service 和 NetworkManager.service并存。
  • Centos8 之后只使用 NetworkManager.service。
  • Ubuntu 17.10之后使用 netplan 前端,NetworkManager/networkd 后端。

network.service

Centos7虽然引入了NetworkManager工具但是,依旧可以使用network.service,直到今年(2024)年centos7才彻底EOL,所以相信大部分系统管理人员包括我自己,依旧停留在network.service管理思路上。

# 开启Centos7上纯粹用network.service管理
systemctl stop NetworkManager
systemctl disable NetworkManager

网络配置修改 /etc/sysconfig/network-scripts 下的 ifcfg-*文件,之后执行 service network restart,配置即可生效。
network.service会执行 /etc/rc.d/init.d/network start 启动网络服务,启动的过程中,使用 ip 命令启动各 device,使用 route 配置系统路由,使用 sysctl 配置等。

ifcfg-*配置参考手册。

NetworkManager

最近公司推动停用Centos7/6,推动升级到RockyLinux 8.x,便在自己机器上装了个RockyLinux 8.10作为Playground熟悉。分分钟装完系统,开机网卡没配置(装机时候特意没开,想着自己配),/etc/sysconfig/network-scripts/目录依旧熟悉,重启网络systemctl restart network报Unit network.service not found,傻了只有NetworkManager,这玩意咱不会啊,先Google条命令nmcli con reload搞定,看来这坑必须填了。

NetworkNanager有两个组件:

  • NetworkManager daemon, 管理连接和监听并报告网络变化。
  • 管理前端, 比如 nmcli,一些 GUI 程序等。

NetworkManager daemon 依赖于 D-Bus 实现了前端管理接口,底层使用 netlink 跟内核交互。nmcli 跟 D-Bus 交互连接 NetworkManager daemon,获得信息以及配置网络。

从NetworkManager的命令行工具nmcli开始:

# nmcli help
Usage: nmcli [OPTIONS] OBJECT { COMMAND | help }

OBJECT
  g[eneral]       NetworkManager's general status and operations
  n[etworking]    overall networking control
  r[adio]         NetworkManager radio switches
  c[onnection]    NetworkManager's connections
  d[evice]        devices managed by NetworkManager
  a[gent]         NetworkManager secret agent or polkit agent
  m[onitor]       monitor NetworkManager changes

所有的操作都针对OBJECT,别的对象按下不表,两个核心的对象必须整明白。

第一个对象是device,也就是设备,怎么理解呢,一个设备对应一个网口,基本上ip link里看到的那些都有对应的设备,基本上可以认为就是物理的网卡,每个物理网卡都会是一个device,当然,有些虚拟的网卡,也会是一个device,比如网桥bridge等。

另外一个对象是connection,也就是连接,就是一系列配置,比如IP地址获取方式是DHCP或者手动配置,如果是手动配置,则配置IP地址,网关,DNS等等信息。

连接最终要被apply到某个device上的,针对同一个device,可以有多个connection,但是有且只能有一个活动的connection被apply到一个device。

结合这个场景就很容易理解了:针对笔记本的无线网卡,在公司,连接的是公司的WIFI,这就需要一个connection,到了家里,连接家里的WIFI,这就是另外一个connection,这俩都是针对同一个device的配置,但是不会同时起作用。这种场景在服务器上不太常见,服务器上基本配置成一个connection对应一个device。

查看设备

nmcli dev
DEVICE  TYPE      STATE      CONNECTION
eth0    ethernet  connected  eth0
lo      loopback  unmanaged  --

可以看到两个设备eth0和lo,其中eth0是以太网类型被NetworkManager管理,对应的连接配置为eth0,状态为connected,lo是loopback目前不被NetworkManager所管理,状态为unmanaged。

查看连接

nmcli con
NAME  UUID                                  TYPE      DEVICE
eth0  4e4a729c-8303-4acf-a636-e8bb97184b14  ethernet  eth0

可以看到所有的连接列表。

查看连接详情

nmcli con show eth0
connection.id:                          eth0
...
ipv4.method:                            auto
...
ipv6.method:                            auto
...

可以看到大量的该连接的配置信息。

添加连接

# 对eth0添加一个静态IP配置的连接命名为eth0-static
nmcli con add type ethernet con-name eth0-static ifname eth0 ipv4.method manual ipv4.addresses "192.168.31.222/24" ipv4.gateway 192.168.31.1 ipv4.dns 192.168.31.1 ipv6.method auto
nmcli con
NAME         UUID                                  TYPE      DEVICE
eth0         4e4a729c-8303-4acf-a636-e8bb97184b14  ethernet  eth0
eth0-static  546f5039-130a-4ac7-af22-afdce2bc8a04  ethernet  --

对eth0添加了一个eth0-static连接,但是当前生效的仍为eth0连接。

切换连接

# 切换过程会导致ssh等连接断开
nmcli con up eth0-static
nmcli con
NAME         UUID                                  TYPE      DEVICE
eth0-static  546f5039-130a-4ac7-af22-afdce2bc8a04  ethernet  eth0
eth0         4e4a729c-8303-4acf-a636-e8bb97184b14  ethernet  --

可以看到现在eth0设备生效的连接为eth0-static。

配置持久化

命令行操作了一大堆,那么这些配置能持久化吗?重启了机器之后还会有么?如果有,那这些配置是保存在哪里的?我能不能不用nmcli这个命令行工具了,使用配置文件,能完成网络的配置么?

这些问题的答案都是肯定的!

首先呢,针对老版本network-scripts,也就是存放在/etc/sysconfig/network-scripts/目录下的那些ifcfg-*开头的配置文件,NetworkManager通过一个ifcfg-rh plugin去识别,这个插件在RHEL里是默认开启的,通过nmcli创建或者修改connections,都会同步到这个目录下对应的配置文件里。另外NetworkManager还会读取/etc/NetworkManager/system-connections/目录下的配置文件,通过nmcli创建和修改的其他类型的connections,比如ovs-bridge, dummy也会同步写入到对应目录下。

ll /etc/sysconfig/network-scripts
-rw-r--r--. 1 root root 269 Aug 16 22:45 ifcfg-eth0
-rw-r--r--  1 root root 349 Aug 17 07:07 ifcfg-eth0-static

所以可以到这两个目录下直接修改配置文件来配置网路,修改后需要手动执行nmcli connection load xxx手动重载单个配置或执行nmcli con reload重新加载所有的配置文件。加载完成后,要想配置真正生效,还需要执行nmcli con down xxx; nmcli con up xxx或者nmcli device reapply xxx来真正让配置生效。

删除连接

nmcli con del eth0-static
Connection 'eth0-static' (546f5039-130a-4ac7-af22-afdce2bc8a04) successfully deleted.
ll /etc/sysconfig/network-scripts
-rw-r--r--. 1 root root 269 Aug 16 22:45 ifcfg-eth0

可以看到命令行删除的eth0-static在/etc/sysconfig/network-scripts目录下的配置文件也同步删除了。

netplan

TODO

参考

https://exfly.github.io/linux_config_network/#netplan
https://www.ichenfu.com/2021/02/16/networkmanager-tutorial/

阅读全文

CentOS 7 EOL 更换YUM源

CentOS 7结束了生命周期(EOL),CentOS官方删除了原mirrorlist子域名的解析,如果仍需要使用CentOS 7系统中的一些安装包,可以如下操作,切换一下yum源。

cp -r /etc/yum.repos.d /etc/yum.repos.d.bak
sed -i -r -e 's|^mirrorlist=|#mirrorlist=|g' -e 's|^#?baseurl=http://mirror.centos.org/centos|baseurl=https://vault.centos.org/centos|g' -e 's|^#?baseurl=http://mirror.centos.org/altarch|baseurl=https://vault.centos.org/altarch|g' -e 's|^#?baseurl=http://download.fedoraproject.org|baseurl=http://download.fedoraproject.org|g' /etc/yum.repos.d/CentOS-*.repo
yum clean all && yum makecache
阅读全文

Alpine Linux DNS问题排查记录

问题现场

kubernetes coredns配置

.:53 {
        errors
        health
        ready
        kubernetes cluster.local in-addr.arpa ip6.arpa {
          pods insecure
          fallthrough in-addr.arpa ip6.arpa
        }
        hosts /etc/coredns/NodeHosts {
          ttl 60
          reload 15s
          fallthrough
        }
        prometheus :9153
        forward . 172.x.8.8 {
          prefer_udp
        }
        cache 30
        loop
        reload
        loadbalance
        log
    }

pod resolv.conf配置

nameserver 10.43.0.10
search default.svc.cluster.local svc.cluster.local cluster.local svc.inner
options ndots:5

预期解析:

  • 集群内service用服务名解析到集群内服务。
  • svc.inner域内forward到172.x.8.8内网dns上,解析到内网dns注册的服务。
  • 其他公共域通过内网172.x.8.8的再上游,同样可以解析。

实际现象:

  • baidu.com在使用ubuntu基础镜像的pod内可以ping通。
  • baidu.com在使用alpine linux 3.15基础镜像的pod内报bad address,其他内网域名但是不是svc.inner域的报could not resolve host。

根因分析

当程序使用系统libc库做dns resolv的时候,走resolv.conf文件的配置,使用非完全限定域(即后面不带".", “baidu.com.“为完全限定,“baidu.com"为非完全限定)且”.“数量不超过ndots配置(这里kubernetes默认是5)时会走search的配置,超过ndots会认为约等于完全限定直接解析。

search逻辑是,在请求域名后面拼上配置的子域,逐个向后搜索解析,如果都找不到最后直接使用请求域名做解析,所以解析域名尝试如下。

baidu.com.default.svc.cluster.local.
baidu.com.svc.cluster.local.
baidu.com.cluster.local.
baidu.com.svc.inner.
baidu.com.

打开集群coredns的日志抓alpine/musl libc的请求解析日志如下:

[INFO] 10.42.0.84:42628 - 64655 "AAAA IN baidu.com.default.svc.cluster.local. udp 53 false 512" NXDOMAIN qr,aa,rd 146 0.000218161s
[INFO] 10.42.0.84:42628 - 64204 "A IN baidu.com.default.svc.cluster.local. udp 53 false 512" NXDOMAIN qr,aa,rd 146 0.00024845s
[INFO] 10.42.0.84:51564 - 50608 "AAAA IN baidu.com.svc.cluster.local. udp 45 false 512" NXDOMAIN qr,aa,rd 138 0.000113998s
[INFO] 10.42.0.84:51564 - 50368 "A IN baidu.com.svc.cluster.local. udp 45 false 512" NXDOMAIN qr,aa,rd 138 0.000119976s
[INFO] 10.42.0.84:55236 - 16067 "AAAA IN baidu.com.cluster.local. udp 41 false 512" NXDOMAIN qr,aa,rd 134 0.00011871s
[INFO] 10.42.0.84:55236 - 15864 "A IN baidu.com.cluster.local. udp 41 false 512" NXDOMAIN qr,aa,rd 134 0.00010077s
[INFO] 10.42.0.84:57937 - 2123 "AAAA IN baidu.com.svc.inner. udp 37 false 512" SERVFAIL qr,rd 37 0.059392615s
[INFO] 10.42.0.84:57937 - 1930 "A IN baidu.com.svc.inner. udp 37 false 512" SERVFAIL qr,rd 37 0.061797511s
[INFO] 10.42.0.84:57937 - 2123 "AAAA IN baidu.com.svc.inner. udp 37 false 512" SERVFAIL qr,rd 37 0.059379512s
[INFO] 10.42.0.84:57937 - 1930 "A IN baidu.com.svc.inner. udp 37 false 512" SERVFAIL qr,rd 37 0.062035159s
[INFO] 10.42.0.84:57937 - 2123 "AAAA IN baidu.com.svc.inner. udp 37 false 512" SERVFAIL qr,rd 37 0.059311395s
[INFO] 10.42.0.84:57937 - 1930 "A IN baidu.com.svc.inner. udp 37 false 512" SERVFAIL qr,rd 37 0.061721482s
[INFO] 10.42.0.84:57937 - 2123 "AAAA IN baidu.com.svc.inner. udp 37 false 512" SERVFAIL qr,rd 37 0.059639921s
[INFO] 10.42.0.84:57937 - 1930 "A IN baidu.com.svc.inner. udp 37 false 512" SERVFAIL qr,rd 37 0.061894263s
[INFO] 10.42.0.84:57937 - 2123 "AAAA IN baidu.com.svc.inner. udp 37 false 512" SERVFAIL qr,rd 37 0.059525564s
[INFO] 10.42.0.84:57937 - 1930 "A IN baidu.com.svc.inner. udp 37 false 512" SERVFAIL qr,rd 37 0.062518585s
[INFO] 10.42.0.84:57937 - 2123 "AAAA IN baidu.com.svc.inner. udp 37 false 512" SERVFAIL qr,rd 37 0.059316764s
[INFO] 10.42.0.84:57937 - 1930 "A IN baidu.com.svc.inner. udp 37 false 512" SERVFAIL qr,rd 37 0.061810188s

ubuntu/glibc的请求日志如下:

[INFO] 10.42.0.75:49573 - 11268 "AAAA IN baidu.com.app-ops.svc.cluster.local. udp 53 false 512" NXDOMAIN qr,aa,rd 146 0.000235088s
[INFO] 10.42.0.75:49573 - 59129 "A IN baidu.com.app-ops.svc.cluster.local. udp 53 false 512" NXDOMAIN qr,aa,rd 146 0.000188461s
[INFO] 10.42.0.75:54693 - 6359 "AAAA IN baidu.com.svc.cluster.local. udp 45 false 512" NXDOMAIN qr,aa,rd 138 0.00012188s
[INFO] 10.42.0.75:54693 - 44242 "A IN baidu.com.svc.cluster.local. udp 45 false 512" NXDOMAIN qr,aa,rd 138 0.000096248s
[INFO] 10.42.0.75:34199 - 10294 "A IN baidu.com.cluster.local. udp 41 false 512" NXDOMAIN qr,aa,rd 134 0.000104275s
[INFO] 10.42.0.75:34199 - 64057 "AAAA IN baidu.com.cluster.local. udp 41 false 512" NXDOMAIN qr,aa,rd 134 0.000173845s
[INFO] 10.42.0.75:42076 - 10254 "A IN baidu.com.svc.inner. udp 37 false 512" SERVFAIL qr,rd 37 0.059601407s
[INFO] 10.42.0.75:42076 - 24081 "AAAA IN baidu.com.svc.inner. udp 37 false 512" SERVFAIL qr,rd 37 0.062046559s
[INFO] 10.42.0.75:42076 - 24081 "AAAA IN baidu.com.svc.inner. udp 37 false 512" SERVFAIL qr,rd 37 0.059077476s
[INFO] 10.42.0.75:42076 - 10254 "A IN baidu.com.svc.inner. udp 37 false 512" SERVFAIL qr,rd 37 0.061514225s
[INFO] 10.42.0.75:52980 - 30220 "AAAA IN baidu.com. udp 27 false 512" NOERROR qr,aa,rd,ra 97 0.000639532s
[INFO] 10.42.0.75:52980 - 39944 "A IN baidu.com. udp 27 false 512" NOERROR qr,rd,ra 77 0.024779792s

baidu.com.svc.inner.在内网dns上肯定是不存在的(我们的内网dns也是用coredns),返回了一个SERVFAIL状态码。

问题就出在这:

  • glibc在DNS服务器返回SERVFAIL后,继续向后搜并最终返回到根域”.“解析获取到了NOERROR 正确的DNS结果。
  • musl libc认为SERVFAIL是DNS服务器的错误,应该报告给调用者,并且不向后继续搜了,并且还不返回到根域”.",所以就获取不到结果了。

musl libc和glibc这个行为差异,有不同的观点,所以至今(2024-07-19)还是这样的行为,也有相关的patch, 如: https://www.openwall.com/lists/musl/2018/03/30/6 并未合并。

个人观点: musl的态度没错,DNS服务器的实现返回的状态码不符合语义,但从客户端兜底和大家都错了这么多年了讲,咱就别较真了呗。

问题解决

最简单的方法:生产别用alpine镜像。

个人当场的解决方法: 因为我是开发环境,没有调用内网其他服务的需要,就在自己集群干掉了svc.inner内网域,没有人返回SERVFAIL了,就没有问题了。

实测一波,把最后一个域改成svc.lan,这个svc.lan forward到内网dns,不是内网的私域会再次forward到公共dns解析,返回NXDOMAIN,musl认为没问题,继续向后搜索到根域,就正确获取结果了。

所以musl libc是对的?DNS服务器的问题: 是自己的域,自己没有记录,为啥返回SERVFAIL。

貌似基于coredns写插件定义dns很容易犯"不标准"这个错?自己遇到不止一次基于coredns开发做权威的问题了,待有空研究研究coredns插件的玩法。

[INFO] 10.42.0.84:55744 - 20786 "AAAA IN baidu.com.default.svc.cluster.local. udp 53 false 512" NXDOMAIN qr,aa,rd 146 0.000199026s
[INFO] 10.42.0.84:55744 - 20370 "A IN baidu.com.default.svc.cluster.local. udp 53 false 512" NXDOMAIN qr,aa,rd 146 0.000095497s
[INFO] 10.42.0.84:47264 - 56647 "AAAA IN baidu.com.svc.cluster.local. udp 45 false 512" NXDOMAIN qr,aa,rd 138 0.000128401s
[INFO] 10.42.0.84:47264 - 56392 "A IN baidu.com.svc.cluster.local. udp 45 false 512" NXDOMAIN qr,aa,rd 138 0.00009345s
[INFO] 10.42.0.84:41203 - 59447 "AAAA IN baidu.com.cluster.local. udp 41 false 512" NXDOMAIN qr,aa,rd 134 0.00014027s
[INFO] 10.42.0.84:41203 - 59202 "A IN baidu.com.cluster.local. udp 41 false 512" NXDOMAIN qr,aa,rd 134 0.000207786s
[INFO] 10.42.0.84:54762 - 27818 "AAAA IN baidu.com.svc.lan. udp 35 false 512" NXDOMAIN qr,aa,rd,ra 110 0.000680326s
[INFO] 10.42.0.84:54762 - 27556 "A IN baidu.com.svc.lan. udp 35 false 512" NXDOMAIN qr,rd,ra 110 0.031160567s
[INFO] 10.42.0.84:35257 - 46005 "A IN baidu.com. udp 27 false 512" NOERROR qr,rd,ra 77 0.008211487s
[INFO] 10.42.0.84:35257 - 46267 "AAAA IN baidu.com. udp 27 false 512" NOERROR qr,rd,ra 97 0.196307927s

其他发现

一番研究alpine/musl libc的dns resolv实现,返现和传统不一致的地方还不止这一处。

alpine linux 3.18/musl libc 1.2.4之前,当dns udp结果大于512字节,会截断就获取不到正确结果了,因为貌似按照rfc截断语义,是这样,没毛病。但是传统大部分resolve实现大于512字节的结果会fallback 使用tcp。

也许是经不住大家diss了,musl终于在去年(2023)加上了dnc fallback tcp的实现,这个commit。

参考链接

https://stackoverflow.com/questions/65181012/does-alpine-have-known-dns-issue-within-kubernetes
https://wiki.musl-libc.org/functional-differences-from-glibc.html#Name-Resolver/DNS
https://git.musl-libc.org/cgit/musl/tree/src/network/lookup_name.c?h=v1.2.4#n190
https://www.openwall.com/lists/musl/2018/03/30/6
https://help.dnsfilter.com/hc/en-us/articles/4408415850003-DNS-return-codes

阅读全文

Rsync工具

rsync是一个用于文件同步和备份的命令行工具,它可以在本地或远程系统之间同步文件和目录。

服务端

全局参数

在文件中[module]之前参数是全局参数,rsync允许使用"[global]“模块名称来指示全局参数部分的开始。

可以在配置文件的全局部分中包含任何模块参数,这样提供的值将成为该参数的默认值。

motd file
此参数允许您指定要在每次连接时显示给客户端的“每日消息”。通常包含站点信息和任何法律声明。默认值为没有motd文件。启动守护进程时,可以通过--dparam=motdfile=FILE命令行选项覆盖此设置。

pid file
此参数告诉rsync守护进程将其进程ID写入该文件。如果文件已经存在,则rsync守护进程将中止而不是覆盖该文件。启动守护进程时,可以通过--dparam=pidfile=FILE命令行选项覆盖此设置。

port
您可以通过指定此值(默认为873)来覆盖守护进程的默认端口号。如果守护进程由inetd运行,则此设置将被忽略,并且将被--port命令行选项所取代。

address
您可以通过指定此值来覆盖守护进程的默认IP地址。如果守护进程由inetd运行,则此设置将被忽略,并且将被--address命令行选项所取代。

socket options
此参数可以为喜欢尽可能调整系统的人提供无尽的乐趣。您可以设置各种可能使传输更快或更慢的套接字选项!有关一些可能设置的选项的详细信息,请参阅setsockopt()系统调用的man页。默认情况下,不设置任何特殊的套接字选项。这些设置也可以通过--sockopts命令行选项指定。

listen backlog
当守护进程侦听连接时,您可以覆盖默认的等待队列长度。默认值为5。

模块参数

comment
该参数指定一个描述字符串,当客户端获取可用模块列表时,该字符串将显示在模块名称旁边。默认情况下没有评论。

path
该参数指定守护程序文件系统中要在此模块中提供的目录。您必须为CWrsyncd.conf中的每个模块指定此参数。

use chroot
如果"use chroot"参数为true,则rsync守护程序将在与客户端开始文件传输之前,将其根目录更改为指定的路径。这样做的好处是能够额外防止可能存在的实现安全漏洞,但缺点是需要超级用户权限,不能跟踪绝对路径或位于新根目录之外的符号链接,并且会复杂化通过名称保留用户和组。

numeric ids
启用此参数会禁用当前守护程序模块中用户和组的名称映射。这将阻止守护程序尝试加载任何与用户/组相关的文件或库。启用此参数使传输行为看起来就像客户端已经传递了--numeric-ids命令行选项。默认情况下,此参数对于chroot模块是启用的,对于非chroot模块是禁用的。除非您采取了确保模块具有必要的资源以进行名称转换并且不可能更改这些资源的步骤,否则不应启用chroot启用的模块上的此参数。

charset
这指定了模块文件名所采用的字符集名称。如果客户端使用 --iconv选项,无论实际传递的字符集是什么,守护进程将使用charset参数的值。这样可以使得守护进程在 chroot 模块中支持字符集转换而无需额外文件,并且确保名称转换以一致的方式进行。如果未设置charset参数,则拒绝 --iconv 选项,就像通过refuse options指定了iconv一样。

max connections
此参数允许您指定允许的最大同时连接数。当达到最大连接数时,任何连接的客户端都会收到一条消息告知他们稍后再试。默认值为0,表示没有限制。负值禁用该模块。还请参阅 lqlock filerq 参数。

log file
当 log file参数设置为非空字符串时,rsync 守护进程将将消息记录到指定的文件中,而不是使用 syslog。如果对每个模块而不是全局设置进行了这个值的设置,全局日志仍将包含任何授权失败或配置文件错误消息。
如果守护进程无法打开指定的文件,它将回退到使用 syslog,并输出关于失败的错误信息。(请注意,以前无法打开指定日志文件被视为致命错误。)

syslog facility
此参数允许您指定从 rsync 守护进程记录消息时要使用的 syslog 设施名称。您可以使用系统上定义的任何标准 syslog 设施名称。常见的名称有 auth、authpriv、cron、daemon、ftp、kern、lpr、mail、news、security、syslog、user、uucp、local0、local1、local2、local3、local4、local5、local6 和 local7。默认值为 daemon。如果log file设置为非空字符串(无论是在每个模块的设置中设置,还是从全局设置继承),此设置将不起作用。

max verbosity
此参数允许您控制守护程序生成的最大冗长信息量(因为这些信息会记录在日志文件中)。默认设置为1,允许客户端请求一级冗长度。

lock file
此参数指定用于支持“max connections”参数的文件。rsync守护程序在该文件上使用记录锁定以确保不超过共享锁定文件的模块的最大连接数限制。默认设置为/var/run/rsyncd.lock。

read only
此参数确定客户端是否可以上传文件。如果“read only”为true,则任何尝试的上传都将失败。如果“read only”为false,则如果守护程序端的文件权限允许,可以进行上传。默认情况下,所有模块都是只读的。

write only
此参数确定客户端是否可以下载文件。如果“write only”为true,则任何尝试的下载都将失败。如果“write only”为false,则如果守护程序端的文件权限允许,可以进行下载。默认情况下,此参数被禁用。

list
此参数确定当客户端请求列出可用模块时,是否应列出此模块。通过将其设置为false,您可以创建隐藏模块。默认情况下,模块是可列出的。

uid
此参数指定在进行与该模块之间的文件传输时应作为守护程序以root身份运行时的用户名或用户ID。与“gid”参数结合使用,确定可用的文件权限。默认设置为-2,通常为用户“nobody”。

gid
此参数指定在进行与该模块之间的文件传输时应作为守护程序以root身份运行时的组名或组ID。这与“uid”参数相辅相成。默认设置为-2,通常为组“nobody”。

fake super
为一个模块设置“fake super = yes”会使守护端表现得好像已经指定了“--fake-user”命令行选项一样。这允许存储文件的全部属性,而无需实际将守护程序运行为root。

exclude
这个参数接受一个以空格分隔的守护进程排除模式列表。与客户端的--exclude选项一样,模式可以使用“-”或“+”来显式指示排除/包含。对于给定的模块,只能应用一个“exclude”参数。有关排除文件如何影响守护进程的详细信息,请参见“filter”参数。

include
使用“include”参数覆盖“exclude”参数的效果。对于给定的模块,只能应用一个“include”参数。有关排除文件如何影响守护进程的详细信息,请参见“filter”参数。

exclude from
该参数指定了守护进程上包含守护进程排除模式的文件的名称,空格分隔。对于给定的模块,只能应用一个“exclude from”参数;如果有多个排除文件,则可以将它们指定为“filter”参数中的合并文件。有关排除文件如何影响守护进程的详细信息,请参见“filter”参数。

include from
类似于“exclude from”的参数,用于守护进程包含模式的文件。对于给定的模块,只能应用一个“include from”参数。有关排除文件如何影响守护进程的详细信息,请参见“filter”参数。

incoming chmod
此参数允许您指定一组逗号分隔的chmod字符串,这些字符串将影响所有传入文件(由守护进程接收的文件)的权限。这些更改发生在所有其他权限计算之后,即使在客户端未指定--perms时,它也会覆盖目标默认和/或现有权限。有关此字符串格式的信息,请参阅--chmod rsync选项的描述和chmod(1)手册页。

outgoing chmod
此参数允许您指定一组逗号分隔的chmod字符串,这些字符串将影响所有传出文件(从守护进程发送的文件)的权限。这些更改首先发生,使发送的权限看起来与存储在文件系统中的权限不同。例如,您可以在服务器上禁用组写入权限,同时对客户端来说它仍然是打开的。有关此字符串格式的信息,请参阅--chmod rsync选项的描述和chmod(1)手册页。

auth users
此参数指定一个以逗号和空格分隔的用户名列表,这些用户名将被允许连接到该模块。这些用户名不需要存在于本地系统上。用户名还可以包含shell通配符字符。如果设置了“auth users”,则客户端将被要求提供用户名和密码来连接到该模块。用于此交换的是挑战-响应身份验证协议。明文用户名和密码存储在“secrets file”参数指定的文件中。默认情况下,所有用户都可以不需要密码连接(称为“anonymous rsync”)。

secrets file
该参数指定包含用于认证此模块的用户名:密码对的文件名。仅当指定了auth users参数时才会查询该文件。该文件以行为基础,每行包含由单个冒号分隔的用户名:密码对。以井号(#)开头的任何行都被视为注释并被跳过。密码可以包含任何字符,但请注意,许多操作系统限制可以在客户端输入的密码长度,因此您可能发现超过8个字符的密码无法工作。

strict modes
此参数确定是否检查秘密文件的权限。如果strict modes为true,则secrets file不得被除rsync守护进程所运行的用户ID之外的任何用户ID读取。如果strict mod为false,则不执行检查。默认值为true。添加此参数是为了适应在Windows操作系统上运行的rsync。

hosts allow
此参数允许您指定与连接客户端的主机名和IP地址匹配的模式列表。如果没有模式匹配,则拒绝连接。

hosts deny
该参数允许您指定与连接客户端的主机名和IP地址匹配的模式列表。如果模式匹配,则拒绝连接。有关更多信息,请参阅“hosts allow”参数。
默认情况下,没有“hosts deny”参数,这意味着所有主机都可以连接。

ignore errors
该参数告诉rsyncd在决定是否运行传输的删除阶段时忽略守护程序上的I/O错误。通常,如果发生任何I/O错误,rsync会跳过--delete步骤,以防止由于临时资源短缺或其他I/O错误而造成灾难性的删除。在某些情况下,此行为是适得其反的,因此您可以使用此参数关闭此行为。

ignore nonreadable
这告诉rsync守护进程完全忽略用户无法读取的文件。这对于可能在目录中包含一些不可读文件的公共存档非常有用,系统管理员不希望这些文件被看到。

transfer logging
此参数启用了按文件的下载和上传进行日志记录,格式与ftp守护进程使用的格式类似。守护进程始终在传输结束时记录传输,因此如果传输被中止,则日志文件中不会提及。

log format
该参数允许您在启用传输日志时指定用于记录文件传输的格式。

timeout
此参数允许您覆盖此模块的I/O超时客户端选择。使用此参数,您可以确保rsync不会永远等待死亡的客户端。超时以秒为单位指定。零值表示没有超时,并且是默认值。对于匿名rsync守护进程,一个不错的选择可能是600(即10分钟超时)。

refuse options
此参数允许您指定一个用空格分隔的rsync命令行选项列表,这些选项将被您的rsync守护进程拒绝。您可以指定完整的选项名称、其一字母缩写或与多个选项匹配的通配符字符串。

dont compress
此参数允许您根据通配符模式选择在从守护程序拉取文件时不应进行压缩的文件名(不存在类似的参数来控制将文件推送到守护程序)。压缩在CPU使用方面是昂贵的,因此通常最好不要尝试压缩无法很好压缩的文件,例如已经压缩过的文件。

pre-xfer exec, post-xfer exec
传输之前和/或之后可以指定要运行的命令。如果pre-xfer exec命令失败,则传输在开始之前被中止。

服务配置示例

uid = nobody
gid = nobody
use chroot = yes
max connections = 4
pid file = /var/run/rsyncd.pid
exclude = lost+found/
transfer logging = yes
timeout = 900
ignore nonreadable = yes
dont compress   = *.gz *.tgz *.zip *.z *.Z *.rpm *.deb *.bz2

[backup]
auth users = root
secrets file = /etc/rsyncd.pass
path = /data1
list = no

客户端

常用参数

-a/--archive
以归档模式进行同步,包括递归复制、保留权限、时间戳等。

-v/--verbose
输出详细的信息。

-P/--progress
显示传输进度。

--password-file
指定秘钥文件

--bwlimit
限制传输带宽,单位为KB,注意不是Kb。

推/拉文件示例

rsync -avP --password-file=/etc/rsync_backup.pass --bwlimit=50000 data_dir 172.x.x.10::backup/
rsync -avP --password-file=/etc/rsync_backup.pass --bwlimit=50000 172.x.x.10::backup/data_dir/ data_dir/
阅读全文