Marco Nie - Linux https://blog.niekun.net/category/Linux/ docker compose 配置自动更新 https://blog.niekun.net/archives/docker-compose.html 2024-08-18T21:42:52+08:00 docker compose 配置文件可以很方便的配置和运行 docker 容器,但每次更新容器都需要运行多条命令。可以通过在 compose 文件中设置 watchtower 来定期自动拉取最新镜像并启动容器,同时可以配置删除旧镜像和容器。在 docker-compose.yml 文件中增加以下内容:version: '3' services: ... watchtower: image: containrrr/watchtower volumes: - /var/run/docker.sock:/var/run/docker.sock command: --interval 3600 --cleanup --remove-volumes environment: - WATCHTOWER_CLEANUP=true - WATCHTOWER_REMOVE_VOLUMES=true以下是主要的配置说明:将 --interval 参数设置为 3600。这意味着 Watchtower 将每 3600 秒(即每小时)检查一次更新。--cleanup 和 WATCHTOWER_CLEANUP=true 确保在更新后清理旧的镜像。--remove-volumes 和 WATCHTOWER_REMOVE_VOLUMES=true 确保删除与旧容器关联的匿名卷。使用这个配置,Watchtower 将:每小时检查一次你的容器是否有更新如果发现更新,它会停止旧容器,启动新容器删除旧的容器和相关的匿名卷删除旧的镜像这个配置应该能满足大多数用例的需求,既能保持你的容器相对最新,又不会过于频繁地进行检查和更新操作。需要注意的是:Watchtower 只会删除它更新的容器的旧版本。它不会删除系统中的其他未使用的容器或镜像。它只删除匿名卷,不会删除命名卷。如果你想删除所有未使用的镜像(不仅仅是 Watchtower 更新的),你可能需要定期运行 docker image prune 命令。 通过浏览器访问服务器指定文件内容 https://blog.niekun.net/archives/3014.html 2024-08-14T15:58:01+08:00 通过 nginx 可以反代服务器指定文件,然后就可以在网页中查看文件内容。核心就是通过 alias 关联文件路径。配置文件如下:location /test.log { alias /home/script/igd/app.log; default_type text/plain; add_header Content-Type "text/plain; charset=utf-8"; charset utf-8; # 确保不会缓存内容 add_header Cache-Control "no-cache, no-store, must-revalidate"; add_header Pragma "no-cache"; add_header Expires "0"; }location 路径替换为需要的路径。alias 设置文件实际路径。 服务器装 warp 解锁 chatgpt https://blog.niekun.net/archives/Linux-warp.html 2024-06-27T15:12:00+08:00 最近在使用 chatgpt 中发现 ios 端无法登录 app,网页端正常使用。提示信息为:Something went wrong. You may be connected to a disallowed ISP If youare using VPN, try disabling it. Otherwise try a different Wi-Fi network or data connection。经过查询发现是我的 vps 服务商只提供网页端 chatgpt 解锁,不支持 app 端。由于 chatgpt 服务也是通过 cloudflare 的 cdn 服务,所以通过将流量转发到 warp 来访问就可以解决问题。首先需要在服务端安装官方的 warp 命令行工具:warp-cli。官方教程:https://developers.cloudflare.com/warp-client/get-started/linux/官方手动添加包仓库教程:https://pkg.cloudflareclient.com/#ubuntu安装在命令行输入以下指令来安装第三方仓库并安装包:# Add cloudflare gpg key curl -fsSL https://pkg.cloudflareclient.com/pubkey.gpg | sudo gpg --yes --dearmor --output /usr/share/keyrings/cloudflare-warp-archive-keyring.gpg # Add this repo to your apt repositories echo "deb [signed-by=/usr/share/keyrings/cloudflare-warp-archive-keyring.gpg] https://pkg.cloudflareclient.com/ $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/cloudflare-client.list # Install sudo apt-get update && sudo apt-get install cloudflare-warp配置安装好后需要注册一个新账户:warp-cli registration new 查看当前账户信息:warp-cli registration show 更换新的 license:warp-cli registration license xxxxx-xxxxxx-xxxxxx 然后需要设置代理模式,可选有:warp, doh, warp+doh, dot, warp+dot, proxy, tunnel_only。我只想要它提供一个 socks5 代理端口即可,所以设置为 proxy 模式,它会在本地 40000 端口监听:warp-cli mode proxy 启动 warp:warp-cli connect 此时 warp 会在本地 40000 端口建立一个 sock5 代理,只需要将需要转发的流量转发到此端口即可走 warp。并且 warp 会自动配置为 Always On 模式,开机自动运行代理。查看 warp 当前配置:# warp-cli settings Merged configuration: (derived) Always On: true (default) Switch Locked: false (user set) Mode: WarpProxy on port 40000 (Not set) WARP tunnel protocol: Wireguard (default) Disabled for Wifi: false (default) Disabled for Ethernet: false (Not set) Resolve via: cloudflare-dns.com @ [162.159.36.1, 2606:4700:4700::1111] (Not set) qlog logging: Disabled (default) Onboarding: true (API defaults) Exclude mode, with hosts/ips: 10.0.0.0/8 100.64.0.0/10 169.254.0.0/16 172.16.0.0/12 192.0.0.0/24 192.168.0.0/16 224.0.0.0/24 240.0.0.0/4 239.255.255.250/32 255.255.255.255/32 fe80::/10 fd00::/8 ff01::/16 ff02::/16 ff03::/16 ff04::/16 ff05::/16 fc00::/7 (default) Fallback domains: intranet internal private localdomain domain lan home host corp local localhost home.arpa invalid test (Not set) Daemon Teams Auth: false (default) Disable Auto Fallback: false (Not set) Allow Updates: true查看代理是否生效:export ALL_PROXY=socks5://127.0.0.1:40000 curl ifconfig.me代理工具转发流量服务端的配置文件需要添加和修改的地方如下:{ "outbounds": [ ... { "protocol": "socks", "settings": { "address": "127.0.0.1", "port": 40000 }, "tag":"socks_out" } ], "router": { "domainStrategy": "AsIs", "rule": [ ... { "tag": "socks_out", "geoDomain": [ { "code": "openai", "filePath": "geosite.dat" } ], "domainMatcher": "mph" } ] }, "inbounds": [ { "protocol": "vmess", ... "sniffing": { "enabled": true, "destOverride": [ "http", "tls" ] }, ...注意需要安装扩展版的 geosite.dat 才有 openai 的条目:https://github.com/Loyalsoldier/v2ray-rules-dat通过访问以下网址测试是否已经解锁 ios app 端:https://ios.chat.openai.com/public-api/mobile/server_status/v1以上就是解决 chatgpt 无法访问的方法。 屏蔽 quic 流量 https://blog.niekun.net/archives/openwrt-quic.html 2024-06-01T15:53:42+08:00 最近在使用一些服务的时候发现流量没有正确的按照设定的规则走,发现部分网站已经优先支持 quic 也就是 http3 协议了,而这种协议目前一些客户端无法正确解析。解决方法就是将 quic 流量屏蔽掉,让那些网站强制走 http 或 http2 即可。quic 协议走的是 udp 层,一般是 443 或 80 端口。openwrt 或其他 linux 系统上使用 nftables 设置规则即可:新建路由表 nft add table ip tabletest # 局域网流量屏蔽 # 局域网流量目标地址是外部地址时传输路径为 prerouting -> forward -> postrouting hooks nft add chain ip tabletest prerouting { type nat hook prerouting priority 0 \; policy accept \; } nft add rule ip tabletest prerouting udp dport { 80, 443 } drop # 本机网关流量屏蔽 # 本机网关流量目标地址时外部地址时传输路径为 本机 -> output -> postrouting hooks nft add chain ip tabletest output { type nat hook output priority 0 \; policy accept \; } nft add rule ip tabletest output udp dport { 80, 443 } drop在 Chrome 中禁用 HTTP/3:打开 Chrome 浏览器在地址栏输入 chrome://flags 并按回车。在搜索框中输入 quic。将 Experimental QUIC protocol 设置为 Disabled。重启浏览器。在 Firefox 中禁用 HTTP/3:打开 Firefox 浏览器。在地址栏输入 about:config 并按回车。接受风险提示。搜索 network.http.http3.enabled。-将其值设置为 false。 修改 pip 为国内源 https://blog.niekun.net/archives/pip.html 2024-05-30T20:02:55+08:00 一键替换命令:# 清华源 pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple # 阿里源 pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/ # 腾讯源 pip config set global.index-url http://mirrors.cloud.tencent.com/pypi/simple # 豆瓣源 pip config set global.index-url http://pypi.douban.com/simple/ # 换回默认源 pip config unset global.index-url nftables 使用教程 https://blog.niekun.net/archives/nftables.html 2024-05-08T10:14:00+08:00 新版本的 openwrt 使用 fw4 防火墙,默认已经从 iptables 切换到了 nftables,语法有了很大的变化,下面介绍 nftables 的使用方法。路由表配置路由表是 nftables 中最顶层的容器,它管理着 chains, sets, maps, flowtables, 和 stateful objects.family 集合每个路由表都只能属于一个 family 集合,可用的 family 有:ip 监听 ipv4 的流量ip6 监听 ipv6 的流量inet 同时监听 ipv4 和 ipv6 的流量arp 监听 ARP-level 地址解析协议的流量bridge 监听 bridge 桥接流量 如交换机netdev 用于监听某个单独网卡的流量基本语法新建路由表:nft add table ip tabletest 以上命令在 ip 集合中新建一个名称为 tabletest 的路由表,可以处理 ipv4 流量路由表列表:# 列出所有路由表 nft list tables # 列出所有 ip 集合的路由表 nft list tables ip删除一个路由表:nft delete table ip tabletest 路由链配置不同于 iptables,nftables 没有预定义的链,如 input output 等。想要在某个环节处理流量,需要定义一个自定义名称的基本链,然后将其挂载在一个特定的 netfilter hook 钩子上。下图是流量包在 linux 网络中的传输路径:外部访问流量传输到本机后如果目标地址是本机,流量传输路径是 prerouting -> input hooks -> 本机,然后经过本机处理后流向 本机 -> output -> postrouting hooks。如果传入本机的外部流量目标地址不是本机,则受 forward hook 监听,这类流量的传输路径是 prerouting -> forward -> postrouting。本机访问外部地址的流量传输路径是 本机 -> output -> postrouting hooks。注意如果本机作为 router 路由使用,需要提前开启 ip 转发功能:echo 1 > /proc/sys/net/ipv4/ip_forward 以下是 netfilter 可用的 chains 和 hooks 列表:基本语法建立基本链,挂载在一个特定 type 的 netfilter hook:nft add chain [<family>] <table_name> <chain_name> { type <type> hook <hook> priority <value> \; [policy <policy> \;] [comment \"text comment\" \;] } 注意,由于 nft 语法使用了特殊字符,如: ;,在命令行中执行需要加转义符 \。或者可以使用单引号 '` 将 nft 后的语句包起来,以下两种写法效果相同:nft add chain ip tabletest input { type filter hook input priority 0 \; } nft 'add chain ip tabletest input { type filter hook input priority 0 ; }' 另一种方法是运行 nft 在交互模式,执行以下命令后就可以不加转义符: nft -i。上面的命令在 tebletest 路由表中新建一个 input 链,挂载在 filter 路由链的 input hook 上。这样就可以监听所有进入本地的流量。priority 决定了所有链的顺序,例如在 filter input hook 上挂载了多个自定义链,通过 priority 决定其执行顺序。数值越低执行优先级越高,例如 -12, -1, 0, 10。如果给多个挂载在同一个 hook 上的自定义基本链同样的 priority,它们的先后执行顺序就是不确定的。添加以下命令后就可以在 tabletest 基本链中监听本机输出的流量:nft 'add chain ip tabletest output { type filter hook output priority 0 ; }' 如果不定义大括号中的内容,也就是不挂载在特定 hook 上,则路由链不会监听任何流量。policy 定义了默认的策略,可用的默认策略为:accept 和 drop,如果路由链中的规则都没有匹配则会应用默认策略:accept 没有匹配到的流量继续在网络层传输drop 没有匹配到的流量被丢弃type 指定自定义路由链挂载到那个基本 chain,可用的基本链:filter, 用于过滤流量包route, 用于重路由,等同于 iptables 的 mangle 路由链的 output hook (其他 mangle hooks 可以使用 filter 代替)nat, 用于运行 Networking Address Translation (NAT). 只有第一个 nat 流量包会匹配到此链剩余的包会跳过此链,因此尽量不要使用此链过滤流量hook 定义了挂载的基本链 hook,可用的 hooks 如下:ingress 只能用于 netdev 和 inet family: 监听来自于 NIC driver 的流量, 早于 prerouting.prerouting: 监听所有在 routing 前的入口流量. 流量可能重定向到 local 或 remote systems.input: 监听所有被路由或重定向到 local system 的入口流量forward: 监听所有不被重定向到 local system 的入口流量output: 监听所有在 local machine 被管理的出口流量postrouting: 监听所有被路由后的即将离开 local system 的出口流量列出一个路由表的所有路由链:nft list ip table tabletest 列出一个路由表的指定路由链:nft list chain ip tabletest output comment 可以给规则添加注释:nft add rule ip tabletest input counter comment \"test comment\" 基本规则配置通过规则可以控制路由链上的流量。基本语法添加规则:nft add rule ip tabletest output ip daddr 8.8.8.8 counter 以上命令会在 tabletest 路由表的 output 链中添加一条规则,匹配出口流量中 ip 地址为 8.8.8.8 的流量并对匹配次数计数,nftables 中 counter 会默认启用即使不写。以上命令相当于 iptables 中的 -A 命令。列出某个链包含的规则:root@OpenWrt:~# nft list chain ip tabletest output table ip tabletest { chain output { type filter hook output priority filter; policy accept; ip daddr 8.8.8.8 counter packets 0 bytes 0 } }下面测试以上规则是否生效,执行以下命令:ping -c 1 8.8.8.8再次查看此链的规则:root@OpenWrt:~# nft list chain ip tabletest output table ip tabletest { chain output { type filter hook output priority filter; policy accept; ip daddr 8.8.8.8 counter packets 1 bytes 84 } }可以看到已经有一次计数了。指定位置添加规则:nftables 中必须通过 handle num 编号来在指定位置添加规则,需要通过 -a 查看链中已经存在的规则的编号:nft -n -a list table ip tabletest -n 可以按数字顺序排号避免出现重复编号。再次查看链中的规则:root@OpenWrt:~# nft -n -a list table ip tabletest table ip tabletest { # handle 4 chain output { # handle 1 type filter hook output priority 0; policy accept; ip daddr 8.8.8.8 counter packets 0 bytes 0 # handle 5 } }handle 5 就是这条规则的编号。下面我们通过 handle 索引在这条规则后添加一条新规则:nft add rule ip tabletest output position 5 ip daddr 127.0.0.8 drop 查看链中的规则:root@OpenWrt:~# nft -n -a list table ip tabletest table ip tabletest { # handle 4 chain output { # handle 1 type filter hook output priority 0; policy accept; ip daddr 8.8.8.8 counter packets 0 bytes 0 # handle 5 ip daddr 127.0.0.8 drop # handle 6 } }如果要在某条规则前插入一条规则需要使用 insert 指令:nft insert rule ip tabletest output position 5 ip daddr 127.1.1.8 drop 查看效果:root@OpenWrt:~# nft -n -a list table ip tabletest table ip tabletest { # handle 4 chain output { # handle 1 type filter hook output priority 0; policy accept; ip daddr 127.1.1.8 drop # handle 7 ip daddr 8.8.8.8 counter packets 0 bytes 0 # handle 5 ip daddr 127.0.0.8 drop # handle 6 } }在某条链最前面添加一条规则:nft insert rule ip tabletest output ip daddr 192.168.2.1 counter 在最前面添加规则就不需要指定 handle 了。替换某条规则:替换一条规则也需要 handle 编号。下面示例会替换 handle 5 为新的规则:nft replace rule ip tabletest output handle 5 ip daddr 1.1.1.1 删除规则:同样的,删除某一条规则也需要获取这条规则的 handle 编号。删除 tabletest 链的 handle 7 规则: nft delete rule ip tabletest output handle 7 删除链中所有规则:nft flush chain ip tabletest output 删除路由表中所有链的所有规则:nft flush table ip tabletest ruleset 层级的操作显示所有 family 的所有 rule 规则:nft list ruleset 显示某一个集合的所有 rule: % nft list ruleset arp % nft list ruleset ip % nft list ruleset ip6 % nft list ruleset bridge % nft list ruleset inet清除所有集合的所有规则:nft flush ruleset 清除某一个集合的所有规则: % nft flush ruleset arp % nft flush ruleset ip % nft flush ruleset ip6 % nft flush ruleset bridge % nft flush ruleset inet备份规则到文件:# 备份所有集合的所有规则 nft list ruleset >> backup.nft # 备份 ip 集合的所有规则 nft list ruleset ip >> backup.nft从文件恢复规则:nft -f backup.nft 以 json 格式显示所有规则:nft --json list ruleset 流量元信息匹配通过 meta 选择器可以进行流量匹配或流量设置。下面简单介绍几个常用的匹配模式,更加详细的参考官方资料:https://wiki.nftables.org/wiki-nftables/index.php/Matching_packet_metainformationiifname 匹配网卡名称:# lo 网卡的入口流量会被接收 nft add rule tabletest input meta iifname lo acceptmark 匹配流量标记:# 流量标记为 123 的出口流量计数 nft add rule tabletest output meta mark 123 counterskgid 匹配流量由特定 gid 用户产生的数据:# 匹配来自 gid 用户 1000 的流量 nft add rule tabletest output meta skgid 1000 counter流量头信息匹配通过 ip {saddr | daddr} 可以匹配 ipv4 的源流量或目标流量:# 匹配来自 192.168.1.100 且去往 192.168.1.1 的流量并计数 # 注意本机地址必须为 192.168.1.1 才可以由 input hook 截获 nft add rule ip tabletest input ip saddr 192.168.1.100 ip daddr 192.168.1.1 counter通过 icmp type 关键词来匹配 icmp 流量,如 ping request:nft add rule ip tabletest input icmp type echo-request counter drop 可以通过命令查询所有可用的 icmp type 类型:root@OpenWrt:~# nft describe icmp type payload expression, datatype icmp_type (ICMP type) (basetype integer), 8 bits pre-defined symbolic constants (in decimal): echo-reply 0 destination-unreachable 3 source-quench 4 redirect 5 echo-request 8 router-advertisement 9 router-solicitation 10 time-exceeded 11 parameter-problem 12 timestamp-request 13 timestamp-reply 14 info-request 15 info-reply 16 address-mask-request 17 address-mask-reply 18通过 ip protocol 匹配 ip family 任意类型的协议:# 匹配所有 tcp 流量 nft add rule ip tabletest output ip protocol tcp # 匹配所有 tcp udp 流量 nft add rule ip tabletest output ip protocol { tcp, udp }通过 meta l4proto 匹配 inet family 任意类型的协议:# tabletest 需要定义为 inet 集合 nft add rule inet tabletest output meta l4proto tcp匹配特定端口的流量:# 丢弃所有端口为 1-1024 的 tcp 流量访问本机 nft add rule ip tabletest input tcp dport 1-1024 counter drop流量匹配动作accept 和 dropdrop 可以对匹配的流量直接丢弃,注意 drop 不能和其他动作组合使用:nft add rule ip tabletest input ip protocol udp drop accept 可以对匹配的流量接收,可以和其他动作组合使用 如 counter 计数:nft add rule ip tabletest input counter accept reject 流量不同于 drop,reject 可以在拒绝流量的基础上进行很多其他动作,如返回给源请求地址无法访问的原因等。如果不指定其他动作,默认会返回源地址一个 ICMP/ICMPv6 port unreachable 的流量包。示例如下:# 拒绝所有 input 的 udp 流量 nft add rule ip tabletest input ip protocol udp reject # 拒绝指定流量并返回 icmp host-unreachable nft add rule ip tabletest input reject with icmp type host-unreachableicmp 可用如下原因:net-unreachable: Destination network unreachable host-unreachable: Destination host unreachable prot-unreachable: Destination protocol unreachable port-unreachable: Destination port unreachable (this is the default) net-prohibited: Network administratively prohibited host-prohibited: Host administratively prohibited admin-prohibited: Communication administratively prohibitedjump 跳转到其他 chain注意只能跳转到同一个路由表的其他 chain。首先我们新建一个 chain:nft add chain ip tabletest tcp-chain 然后定义这个链的规则:nft add rule ip tabletest tcp-chain counter 然后可以定义将所有匹配的流量跳转过去:ft add rule ip tabletest input ip protocol tcp jump tcp-chain 以上示例实现的就是将所有 input 的 tcp 流量跳转到 tcp-chain 计数,然后就返回原始 input 环节继续流转。log 日志通过 log 可以记录匹配到的流量信息,在系统日志中可以查看到。下面是一个示例,可以记录所有对本机的 ping 请求:nft add rule ip tabletest input icmp type echo-request log prefix \"New ping request: \" accept从局域网对本机进行 ping 后,系统日志如下:Thu May 9 11:58:04 2024 kern.warn kernel: [ 3741.786865] New ping request: IN=br-lan OUT= MAC=00:0c:29:c5:39:8d:00:50:56:c0:00:02:08:00 SRC=192.168.244.2 DST=192.168.244.1 LEN=60 TOS=0x00 PREC=0x00 TTL=128 ID=49655 PROTO=ICMP TYPE=8 CODE=0 ID=1 SEQ=6609网络地址转换nat 链类型可以执行网络地址转换的功能,这种链类型有其特有的属性:流量中只有第一个包会被用来进行匹配规则流量包中后续的流量不会被检查nat 链类型特有的规则赋予其他链类型会报错先定义一个 nat 类型的基本链:nft add chain ip tabletest postrouting { type nat hook postrouting priority 0 \; } 以上定义了一个 nat 类型的基本链挂载在 postrouting hook 上。snat 表示源地址。下面的规则可以将来自 192.168.1.0/24 从 eth0 网卡发出的流量在发送出去的时候,将源地址修改为 1.2.3.4nft add rule ip tabletest postrouting ip saddr 192.168.1.0/24 oif eth0 snat to 1.2.3.4 也可以定义一个地址范围:# 将所有 tcp 流量的源地址都修改为指定的ip范围内 nft add rule ip tabletest postrouting ip protocol tcp snat ip to 10.0.0.1-10.0.0.100:3000-4000下面介绍如何修改目标地址,再定义一个 nat 类型的基本链:nft add chain ip tabletest prerouting { type nat hook prerouting priority 0 \; } 以上定义了一个 nat 类型的基本链挂载在 prerouting hook 上。dnat 表示目标地址。下面规则会将要进入 eth0 的 tcp 80 443 端口的流量的目标地址改为 192.168.1.120 也就是重定向:nft 'add rule ip tabletest prerouting iif eth0 tcp dport { 80, 443 } dnat to 192.168.1.120' redirect 是一种特殊的 dnat,它会将流量重定向到本机设备上:nft add rule ip tabletest prerouting tcp dport 22 redirect to 2222 以上规则会将进入的 tcp 22 端口的流量转发到本机 2222端口上。需要注意的是 redirect 只能应用于 nat 链类型的 prerouting 和 output hooks。设置流量包元信息设置 mark 标记:nft add rule ip tabletest output mark set 123 set 架构nftables 提供了 set 架构可以用任意支持的选择器来搭建 sets。匿名 set匿名 set 是直接定义在 rule 内的 set,它没有特定的名称,也不可以更新 set 中的元素,下面是一个示例:nft add rule ip tabletest output tcp dport { 22, 23 } counter { 22, 23 } 就属于一个匿名 set。规则会去尝试匹配 set 中的每个元素。非匿名 set可以通过 nft add set 来创建一个有名称的 set,例如:nft add set ip tabletest blackhole { type ipv4_addr \; comment \"drop all packets from these hosts\" \; } blackhole 就是这个 set 的名称,后续可以再 rule 中使用。set 类型指定是 ipv4 数据。set 名称需要小于等于16个字符,comment 注释是可选项。可用的 type 类型有:ipv4_addr: IPv4 addressipv6_addr: IPv6 address.ether_addr: Ethernet address.inet_proto: Inet protocol type.inet_service: Internet service (read tcp port for example)mark: Mark type.ifname: Network interface name (eth0, eth1..)建立好之后就可以往 set 里添加元素了:nft add element ip tabletest blackhole { 192.168.3.4 } nft add element ip tabletest blackhole { 192.168.1.4, 192.168.1.5 }如果要添加一个 ip 网段则需要将 set 定义 flags interval:nft add set ip tabletest blackhole { type ipv4_addr \; flags interval \; } 然后就可以添加一个 ip 网段了:nft add element ip tabletest blackhole { 192.168.1.0/24 } 可以查询 set 中现有的元素:root@OpenWrt:~# nft list set ip tabletest blackhole table ip tabletest { set blackhole { type ipv4_addr comment "drop all packets from these hosts" elements = { 192.168.1.4, 192.168.1.5, 192.168.3.4 } } }下面就可以通过 set 名称在 nftables 规则中应用:nft add rule ip tabletest input ip saddr @blackhole drop nft add rule ip tabletest output ip daddr != @blackhole accept以上就是 natables 的基本用法。参考链接nftables HOWTO documentation pageNftables familiesNetfilter hooksOperations at ruleset level 通过 dnsmasq nftset 和 nftables 对域名流量的控制 https://blog.niekun.net/archives/dnsmasq-nftset-nftables-1.html 2024-05-07T10:31:00+08:00 最近升级路由器系统到 openwrt 23,发现 dnsmasq-full 已经默认不支持 ipset 转而支持 nftset 了,所以之前的教程:通过 dnsmasq ipset 和 iptables 对域名流量的控制 已经不适用新版本系统。下面介绍如何通过 nfset 和 nftables 实现同样的功能。首先查看 dnsmasq 版本是否支持 nftset:root@OpenWrt:~# dnsmasq -v Dnsmasq version 2.90 Copyright (c) 2000-2024 Simon Kelley Compile time options: IPv6 GNU-getopt no-DBus UBus no-i18n no-IDN DHCP DHCPv6 no-Lua TFTP conntrack no-ipset nftset auth cryptohash DNSSEC no-ID loop-detect inotify dumpfile可以看到其中有 nftset 字样,如果没有就需要安装 dnsmasq-full,安装教程参考:dnsmasq 使用教程。nftables 提供 set 功能可以在一个路由表中建立特定名称一个 ip 库,并通过命令 ip daddr 索引库里的地址。关于 nftables 的使用教程参考:nftables 使用教程先建立一个任意名称的路由表:nft add table tabletest 然后给这个路由表建立一个名称为 iplist 的 ip 库,类型定义为 ipv4 地址:nft add set ip tabletest iplist { type ipv4_addr\; } 如果要添加一个 ip 网段,必须定义 ip 库属性:flags intervalnft add set ip tabletest iplist { type ipv4_addr \; flags interval \; } 现在就可以给这个 ip 库里添加 ip 地址了,命令如下:nft add element ip tabletest iplist { 111.22.33.4 }; nft add element ip tabletest iplist { 111.22.33.4/16 }; 可以通过命令查看这个 ip 库里包含的所有地址:root@OpenWrt:~# nft list set ip tabletest iplist table ip tabletest { set iplist { type ipv4_addr flags interval elements = { 111.22.33.4, 111.22.33.4/16 } } }通过 dnsmasq 配置文件也可以添加指定域名解析出的 ip 地址到 nftset 对应 ip 库列表中,例如在 /etc/dnsmasq.conf 配置文件中添加以下指令:nftset=/qq.com/4#ip#tabletest#iplist 重启 dnsmasq 服务:service dnsmasq restart 查询一下 qq.com 的 ip 地址:root@OpenWrt:~# nslookup qq.com Server: 127.0.0.1 Address: 127.0.0.1:53 Non-authoritative answer: Name: qq.com Address: 157.255.219.143再次查看 iplist 表里包含的 ip 地址:root@OpenWrt:~# nft list set ip tabletest iplist table ip tabletest { set iplist { type ipv4_addr flags interval elements = { 111.22.33.4, 111.22.33.4/16, 157.255.219.143 } } }可以看到 qq.com 解析出来的 ip 地址已经放入了 iplist 表中。nftables 可以识别并处理 nftset 表中的 ip 地址,这样就可以做到对指定域名的流量控制。新建的自定义路由表需要首先指定某个动作链条属于什么动作链类型。如:# 定义 tabletest 的 output 链,类型为 filter 路由链的动作链 "output" # 优先级 0 表示:(在任何路由决策前捕获传入数据包) # 策略为 accept 表示没有匹配流量后继续传入后续路由表及规则进行匹配 nft add chain tabletest output { type filter hook output priority 0 \; policy accept \; } # 定义 tabletest 的 prerouting 链,类型为 NAT 路由链的动作链 "prerouting" nft add chain tabletest prerouting { type nat hook prerouting priority 0 \; policy accept \; }nftables 规则处理 set 库里 ip 地址的流量:# 屏蔽本机对 iplist 库中 ip 地址的访问 nft add rule tabletest output ip daddr @iplist drop # 目标地址为 set 库地址的prerouting tcp 流量转发到指定端口 nft add rule tabletest prerouting ip daddr @iplist ip protocol tcp redirect to :1081列出指定路由表定义的规则:root@OpenWrt:~# nft list table tabletest table ip tabletest { set iplist { type ipv4_addr flags interval elements = { 111.22.33.4, 111.22.33.4/16, 157.255.219.143 } } chain output { type filter hook output priority filter; policy accept; ip daddr @iplist drop } chain prerouting { type nat hook prerouting priority filter; policy accept; ip daddr @iplist ip protocol tcp redirect to :1081 } }删除一个路由表:nft delete table tabletest 删除一个路由表中所有规则,保留路由链定义:nft flush table tabletest 删除指定路由表中某个路由链中的所有规则:nft flush chain tabletest output 参考链接fw4 Filtering traffic with IP sets by DNSnftablesSimple rule managementConfiguring tablesConfiguring Shadowsocks rules with nftset in OpenWRT 23 openwrt 系统升级 https://blog.niekun.net/archives/openwrt-1.html 2024-04-02T10:26:03+08:00 小版本升级小版本升级,例如 19.05-> 19.07。这种小版本的升级最方便的就是通过 Attended Sysupgrade 功能,可以保留已安装的包和系统设置。最大限度地无缝过渡。官方介绍:https://openwrt.org/docs/guide-user/installation/attended.sysupgrade需要先安装 Attended Sysupgrade luci 界面包:opkg install luci-app-attendedsysupgrade 建议使用此功能前依然做一次数据备份。然后重新登录 luci,在 system - Attended Sysupgrade 找到入口,点击 search for firmware upgrade 即可在线搜索可更新的系统。大版本升级最方便的就是通过 luci 界面升级系统,目前支持直接升级的大版本顺序是:19.07 > 21.02 > 22.03 > 23.05。大版本升级改动openwrt 21:https://openwrt.org/releases/21.02/notes-21.02.0WPA3 support included by defaultTLS and HTTPS support included by defaultLuCI is now available over HTTPSInitial DSA support replaces the swconfig systemNew network configuration syntax and board.json changeKernel with container supportopenwrt 22:https://openwrt.org/releases/22.03/notes-22.03.0Firewall4 based on nftables,superseding the iptables-based firewall3Dark mode in LuCIopenwrt 23:https://openwrt.org/releases/23.05/notes-23.05.0Switch from wolfssl to mbedtls as default,TLS 1.3 SupportRust Package Support数据备份每个版本升级实际上就是重新刷入了一次固件,所以之前的配置文件什么的基本上都会被覆盖,所以系统内修改过的配置最好做一次备份。打开 luci 界面,选择 system - backup/flash firmware,在 configuration 菜单栏中将需要保存的文件或目录定义出来,然后在 action 菜单栏中选择 backup - generate archive 即可保存备份到本地。已安装包列表可以通过 awk 脚本识别出自己手动安装的包列表,方便更新系统后安装回去,下载脚本:https://github.com/richb-hanover/OpenWrtScripts/blob/main/opkgscript.sh执行以下命令会保存已安装的包列表到 /etc/config/opkg.installed:opkgscript.sh -v write 执行以下命令会识别并安装 /etc/config/opkg.installed 列表中的包:opkgscript.sh -v install 也可以执行以下 awk 脚本可以单独列出自己手动安装的包列表:#!/usr/bin/awk -f BEGIN { ARGV[ARGC++] = "/usr/lib/opkg/status" cmd="opkg info busybox | grep '^Installed-Time: '" cmd | getline FLASH_TIME close(cmd) FLASH_TIME=substr(FLASH_TIME,17) } /^Package:/{PKG= $2} /^Installed-Time:/{ INSTALLED_TIME= $2 # Find all packages installed after FLASH_TIME if ( INSTALLED_TIME > FLASH_TIME ) { cmd="opkg whatdepends " PKG " | wc -l" cmd | getline WHATDEPENDS close(cmd) # If nothing depends on the package, it is installed by user if ( WHATDEPENDS == 3 ) print PKG } } EOF保存以上内容到 listuserpackages.awk 文件中并执行即可列出用户自行安装包列表。下载升级固件x86 版本的 openwrt 的升级固件就是全新安装时候用的固件,直接在官网下载需要版本的 gz 压缩包即可。下载地址:https://downloads.openwrt.org/releases/我下载的是:generic-ext4-combined.img.gz,注意不要解压出来,保留压缩包即可。进入 luci 的 system - backup/flash firmware 选择 Flash image ,然后选择刚才下载的压缩包即可上传更新,会提示是否保留设置和配置,跨大版本的升级必须取消选择保留数据,否则可能升级失败:如果升级后卡在 grub 界面说明可能是由于选择了保留配置导致升级失败了,可以参考官方教程通过 failsafe mode 恢复默认配置:Failsafe mode, factory reset, and recovery mode,或者直接重新安装系统。网络配置稍等几分钟安装好后你可能会发现 luci 无法在局域网中访问了,这是由于新安装的固件恢复了 network 配置,需要直接到 openwrt 设备上配置网络。配置教程参考:openwrt network 配置配置好网络后在局域网设备中可以用 ssh 登录了,此时会发现提示:@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY! Someone could be eavesdropping on you right now (man-in-the-middle attack)! It is also possible that a host key has just been changed. The fingerprint for the RSA key sent by the remote host is SHA256:U9XODs/7A4k065pxSMyEtQ2m98v2P0bf/ML0MfzU. Please contact your system administrator. Add correct host key in C:\\Users\\Marco Nie/.ssh/known_hosts to get rid of this message. Offending RSA key in C:\\Users\\Marco Nie/.ssh/known_hosts:6 Host key for 192.168.244.1 has changed and you have requested strict checking. Host key verification failed.这是由于更新系统后 ssh 指纹发生了变化,需要删除本地缓存的 openwrt 设备的指纹在登陆,windows 系统 ssh 指纹保存地址为当前用户目录下的 .ssh 文件夹。升级后续升级后可以通过之前的脚本列出的已安装包的列表将自己需要的包安装回去,同时将备份数据按照新系统的格式恢复回去。从 openwrt 21 开始修改了 network 配置文件格式,参考:https://blog.niekun.net/archives/2291.html从 openwrt 22 开始替换 iptables 为 nftables,需要原始工具的话可以自行安装回去:opkg install iptables参考链接Opkg package managerOpenWRT 19.07 to 21.02.0 upgrade Linux 查询及编辑用户及用户组 https://blog.niekun.net/archives/Linux.html 2024-04-01T16:20:00+08:00 查询当前所有用户compgen -u 查询当前所有用户组compgen -g 添加一个用户到某个组sudo usermod -a -G groupName userName newgrp groupName 删除一个用户从某个组sudo usermod -G groupName userName newgrp groupName 用户和组对文件的权限管理参考:chown 和 chmod 管理文件权限 openwrt 添加新用户 https://blog.niekun.net/archives/openwrt.html 2024-03-29T11:19:26+08:00 安装好 openwrt 后默认有一个 root 用户,需要添加新用户也很简单,只需要在 /etc/passwd 文件最后按照格式增加一个用户即可,然后可以修改这个新用户的密码。下面使用一条命令快速添加新用户:grep -qw new_user /etc/passwd || echo "new_user:x:0:23333:::" >> /etc/passwd 命令先检查是否在文件中存在需要添加的用户名,如果不存在则在文件最后一行添加用户。其中 new_user 是用户名,0 是 uid,23333 是 gid。如果需要修改这个新用户的密码,执行命令即可:passwd new_user 以上就是创建新用户简单方法。