跳转到主要内容

踩坑瞎记录

个人无前因后果的踩坑瞎记录。
有时候累了并不想深入分析,或者是懂了但懒得系统的写出来,所以就瞎记录一下,排版也懒得排,也懒得翻译。
因此本文可能存在未经核实的内容。
也可能顺便记录下偶尔会用到的东西。

随着时间推移,内容可能越来越多,桌面端请查看页面左边的页面导航。

DELL 服务器使用第三方 PCIe 设备后风扇转速高(90%)

反正就是非 DELL 认证设备,由于没有热量信息,服务器直接给你风扇拉到 90% 来保证散热。

yum install OpenIPMI OpenIPMI-tools

将第三方 PCIe 卡默认冷却响应逻辑设置为禁用(风扇正常):

ipmitool -I lanplus -H -U -P raw 0x30 0xce 0x00 0x16 0x05 0x00 0x00 0x00 0x05 0x00 0x01 0x00 0x00

将第三方 PCIe 卡默认冷却响应逻辑设置为启用(风扇拉满):

ipmitool -I lanplus -H -U -P raw 0x30 0xce 0x00 0x16 0x05 0x00 0x00 0x00 0x05 0x00 0x00 0x00 0x00

-H 填 iDRAC IP 地址
-U 填 iDRAC 用户名
-P 填 iDRAC 密码

如果关了散热不够,可以去 iDRAC 里面给风扇加个正向 offset(什么时候发明个 onset 什么的),不过也没有反向的给你加就是了。

参考:https://serverfault.com/questions/715387/how-do-i-stop-dell-r730xd-fans-from-going-full-speed-when-broadcom-qlogic-netxtr

网卡能识别,但不通,网卡灯不亮

反正就是系统里看着一切正常,ip a、ifconfig、lspci 都能识别,但就是不能用。

或者是全速跑一段时间后断开,端口完全无反应。

可能是网卡过热了,自动保护。

我有一张 X540-AT2 是这样的,这东西似乎也没有温度传感器,连 I350 都有。

Openwrt IPv6 不通

表现为能正常获取地址,但是从路由器 ping IPv6 显示 network unreachable,从 Windows ping IPv6 显示 网络不可达。

可能原因:

网络  -> 负载均衡(MultiWAN 管理器)-> 策略  -> 备用成员是 unreachable(不可达)而不是 default (默认使用主路由表)

所以把所有策略的备用成员都改成 default 就行了。

具体干嘛的没研究过,因为我也没使用多播、多 WAN。然而这居然会影响网络,不好评价。

另外我不确定默认是否开了 IPv6 MSS 钳制。(IPv6 包头长度和 IPv4 不一样,不开 MSS 钳制容易导致 PMTU 黑洞)

MSS 钳制在
网络  -> 防火墙 -> 区域 -> 编辑 -> MSS 钳制

iptables

使用 iptables -t mangle -L -vip6tables -t mangle -L -v 检查是否有类似规则:

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
 0     0 TCPMSS      tcp  --  any    any     anywhere             anywhere             tcp flags:SYN,RST/SYN TCPMSS clamp to PMTU

不确定的话可以尝试直接在启动脚本里面手动加一下:

# 示例
ip6tables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -o <接口名> -j TCPMSS --clamp-mss-to-pmtu

# 例子
ip6tables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -o pppoe0 -j TCPMSS --clamp-mss-to-pmtu
ip6tables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -o pppoe-wan -j TCPMSS --clamp-mss-to-pmtu
ip6tables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -o wan -j TCPMSS --clamp-mss-to-pmtu
ip6tables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -o wan6 -j TCPMSS --clamp-mss-to-pmtu
ip6tables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -o wan6_6 -j TCPMSS --clamp-mss-to-pmtu

# 不指定接口
ip6tables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

当然新版系统很可能已经没有 iptables 或 ip6tables,而是直接使用 nftables,即安装的是 firewall4 包。

nftables

nftables 使用 nft list ruleset 检查是否有类似规则,我这里给 lan 也开了:

        chain mangle_forward {
                type filter hook forward priority mangle; policy accept;
                iifname "br-lan" tcp flags syn tcp option maxseg size set rt mtu comment "!fw4: Zone lan IPv4/IPv6 ingress MTU fixing"
                oifname "br-lan" tcp flags syn tcp option maxseg size set rt mtu comment "!fw4: Zone lan IPv4/IPv6 egress MTU fixing"
                iifname "pppoe-wan" tcp flags syn tcp option maxseg size set rt mtu comment "!fw4: Zone wan IPv4/IPv6 ingress MTU fixing"
                oifname "pppoe-wan" tcp flags syn tcp option maxseg size set rt mtu comment "!fw4: Zone wan IPv4/IPv6 egress MTU fixing"
        }

如果你没有的话可以尝试启动脚本里面手动加一下:

# 创建 mangle 表(可能不需要)
nft add table inet mangle

# 添加 mangle_forward 链(可能不需要)
sudo nft 'add chain inet mangle mangle_forward { type filter hook forward priority mangle; policy accept; }'

# 添加 MSS 钳制规则
sudo nft 'add rule inet mangle mangle_forward iifname "br-lan" tcp flags syn tcp option maxseg size set rt mtu comment "!fw4: Zone lan IPv4/IPv6 ingress MTU fixing"'
sudo nft 'add rule inet mangle mangle_forward oifname "br-lan" tcp flags syn tcp option maxseg size set rt mtu comment "!fw4: Zone lan IPv4/IPv6 egress MTU fixing"'
sudo nft 'add rule inet mangle mangle_forward iifname "pppoe-wan" tcp flags syn tcp option maxseg size set rt mtu comment "!fw4: Zone wan IPv4/IPv6 ingress MTU fixing"'
sudo nft 'add rule inet mangle mangle_forward oifname "pppoe-wan" tcp flags syn tcp option maxseg size set rt mtu comment "!fw4: Zone wan IPv4/IPv6 egress MTU fixing"'

Windows 系统修复命令组

遇事不决修一下

sfc /SCANNOW

Dism /Online /Cleanup-Image /ScanHealth

Dism /Online /Cleanup-Image /CheckHealth

DISM /Online /Cleanup-image /RestoreHealth

sfc /SCANNOW

Windows 网络修复小连招

ipconfig /release 释放 IP 地址会暂时导致网络中断

ipconfig /release

ipconfig /flushdns

ipconfig /renew

netsh int ip reset

netsh winsock reset

在 pg_dumpall 或 pg_dump 中使用 .pgpass 无效

我是服气的,反正文档没说。

pg_dumpall 提到支持使用 .pgpass 文件,然后 .pgpass 提到使用方法是放到默认路径或者环境变量指定路径。

比如:

export PGPASSFILE=/somewhere/.pgpass

然后 .pgpass 的格式是 hostname:port:database:username:password ,前四位可以使用 * 作为通配符,且必须用 chmod 0600 保护。
例如:

localhost:5432:postgres:postgres:verysecuritypassword

那么你是不是觉得该这样使用 pg_dumpall:

export PGPASSFILE=/somewhere/.pgpass && pd_dumpall > foobar.sql

这样你只会得到:pg_dumpall: 错误: 连接到套接字"/run/postgresql/.s.PGSQL.5432"上的服务器失败:致命错误:  角色 "root" 不存在

怎么回事呢?

原来 .pgpass 可以包含多行,于是 pg_dumpall 会去扫描每一行,和你提供的命令行参数匹不匹配。
比如,如果 .pgpass 中的 hostname 匹配 pg_dumpall --host 并且 .pgpass 中的 port 匹配 pg_dumpall --port ……,那么它将使用此文件中提供的密码。
如果某些内容不匹配,pg_dumpall 将忽略 .pgpass 里的该行内容。

所以实际上,你需要至少在命令行中指定用户名和主机名:

export PGPASSFILE=/somewhere/.pgpass && pd_dumpall -U postgres -h localhost > foobar.sql

因此 .pgpass 前几个值可以使用通配符:

*:*:*:postgres:verysecuritypassword


路由追踪有一跳的 IP 属于 DoD Network Information Center — defense.gov 美国国防部但延迟很低

从阿里云、腾讯云等云追踪路由,发现其中一跳的 IP 的拥有者 AS749 是美国国防部 defence.gov

# nexttrace 119.29.29.29
NextTrace v1.2.9 2024-03-04T14:32:40Z f96c3e5
[NextTrace API] preferred API IP - 45.88.195.154 - 1495.89ms - DMIT.LAX
IP Geo Data Provider: LeoMoeAPI
traceroute to 119.29.29.29, 30 hops max, 52 bytes packets
1   11.2.19.129     *                         DOD
                                              0.62 ms / 0.49 ms / 0.49 ms
2   11.2.58.98      *                         DOD
                                              0.64 ms / 0.66 ms / 0.60 ms
3   10.196.24.85    *                         RFC1918
                                              100.75 ms / 100.72 ms / * ms
4   10.162.34.113   *                         RFC1918
                                              4.67 ms / 4.03 ms / 3.93 ms
    [MPLS: Lbl 53380, TC 5, S 0, TTL 1]
    [MPLS: Lbl 49167, TC 5, S 1, TTL 1]
5   10.200.8.249    *                         RFC1918
                                              5.58 ms / 4.58 ms / 4.79 ms
    [MPLS: Lbl 48045, TC 5, S 0, TTL 1]
    [MPLS: Lbl 49167, TC 5, S 1, TTL 2]
6   119.29.29.29    AS132203 [TencentCloud]   DNSPod Public DNS+      tencent.com
    pdns.dnspod.cn                            8.26 ms / 8.23 ms / 8.23 ms
MapTrace URL:

可见前两跳 11.2.19.129 和 11.2.58.98 都属于 AS749,而 AS749 所有者为 DoD Network Information Center,IP 位置判断为 美国 堪萨斯州。

但从可见延迟非常低,看起来像内网。

 这是因为这些公有云内网地址不够用,所以把美国国防部所有的地址拿来当内网地址使用了,并不是真的在美国,实际属于内网地址。

 

为什么用美国国防部的地址?

因为美国国防部没有在公网上宣告/使用这些地址,所以理论上不会影响联网。
但如果某一天它宣告了这些地址的路由,那么你的包很可能就会乱走了,所以有一定风险。

Alpine Linux 启用 IPv6

Alpine 为了轻量化,默认没有开启 IPv6,接口也是在执行安装脚本的时候设置的。

按照官方文档

要自动设置 IPv6:

打开 /etc/network/interfaces

添加一行 iface eth0 inet6 auto 就可以了?

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp
iface eth0 inet6 auto

auto eth1
iface eth1 inet dhcp
iface eth1 inet6 auto

然而当你 service networking restart 后发现并没有 IPv6 地址。

其实文档里还说

IPv6 DHCP Configuration

Alpine's use of ifupdown-ng supports three DHCP clients: udhcpc, dhclient, and dhcpcd. Of these, only dhcpcd can interact with both DHCP and DHCPv6 from the same process, which ifupdown-ng requires. Thus the IPv4 DHCP configuration given above will also result in the use of DHCPv6, but only if you install the dhcpcd package. (The ifupdown-ng scripts prioritize dhclient over udhcpc, and they prioritize dhcpcd over dhclient; see /usr/libexec/ifupdown-ng/dhcp.)


IPv6 DHCP 配置

Alpine 使用 ifupdown-ng 支持三种 DHCP 客户端:udhcpc、dhclient 和 dhcpcd。其中,只有 dhcpcd 可以从同一进程与 DHCP 和 DHCPv6 交互,这是 ifupdown-ng 所需要的。因此,上面给出的 IPv4 DHCP 配置也将导致使用 DHCPv6,但前提是您安装了 dhcpcd 软件包。 (ifupdown-ng 脚本优先考虑 dhclient 优先于 udhcpc,并且优先考虑 dhcpcd 优先于 dhclient;请参阅/usr/libexec/ifupdown-ng/dhcp。)


摘自 https://wiki.alpinelinux.org/wiki/Configure_Networking(经过机器翻译)

所以你还需要 apk add dhcpcd 再重启网络应该就能拿到 IPv6 地址了。

802.3ad LACP 链路聚合也可以在接口间平衡流量?

RedHat Insights 告诉我:

Decreased network performance when using an incorrect LACP hash in networking bonding

In bonding mode 2 or 4, network traffic is not distributed to all port interfaces due to an incorrect hash policy. This results in decreased network performance.

These systems are affected by this issue because an incorrect LACP hash bundled with mode 2 or mode 4 is detected.


在网络绑定中使用不正确的 LACP 哈希时,网络性能会降低

在绑定模式 2 或 4 下,由于哈希策略不正确,网络流量未分配到所有端口接口。 这会导致网络性能下降。

这些系统受此问题影响,因为检测到与模式 2 或模式 4 捆绑的不正确的 LACP 哈希。


摘自 https://console.redhat.com/insights/advisor/recommendations(经过机器翻译)(个性化内容)


详见:https://access.redhat.com/solutions/666853

模式 4 就是 802.3ad,根据知识库文章,就是加上  xmit_hash_policy=layer2+3 就行了

BONDING_OPTS="mode=802.3ad lacp_rate=fast miimon=100 xmit_hash_policy=layer2+3"

但是不要用 layer3+4 因为不符合 802.3ad 规范。

然后单流(单会话)是不可能在多个接口上平衡的。因为交换机中没有任何东西可以保证到达多个交换机端口的流量按传输或接收的顺序传递。这种流量重新排序会严重损害 TCP 提高 TCP 窗口以实现良好性能的能力,并且会导致 TCP 拥塞控制激活,从而缩小 TCP 窗口,从而导致性能不佳。流量重新排序还会导致接收方无序接收 UDP 流量。如果接收应用程序没有预料到这一点和/或应用程序协议未实现数据排序,则可能会出现数据错误。

Meta Quest 3 + Virtual Desktop 1.32.2 很快断连

1.30.5 就不会断,1.32.4 也会,差不多 2 分钟就会断联,Wireshark 抓包发现头显总是莫名其妙发送 RST 包,再查看之前的包发现似乎是握手失败导致超时发送 RST 包,其他端口包正常发生所以画面正常,然后发送该 RST 后,向其他正常的端口也发送了多个 RST 包导致连接直接断开。

网络拓扑 

光猫 -> 小米 AIoT 路由器 AX3600 OpenWrt 魔改1G 内存版 -> TP-Link AP TL-7AP5100HC-PoE/DC易展版

AX3600 拨号,PC 有线接入 AX3600,Wifi 设备皆接入 AP,AX3600 Wifi 关闭。

各种办法(包括关闭 IPv6、更换路由器等)排查无效, 而且 Virtual Desktop 1.30.5 版本不会断,给排查造成了很大困难。
(另外似乎 Quest 3 目前版本 V64+ 不推荐开启 IPv6,因为收到某种包时系统会发生小型崩溃,表现为 Wifi 断开。讨论1讨论2讨论3

最后 PC 也连 Wifi(Intel AX201)发现没问题,所以罪魁祸首是 Intel 有线网卡。

结论:英特尔® 以太网控制器 I225-V  干的,虽然只在 1Gbps 连接速度上使用,而且安装了制造商推荐驱动,但是还是它干的。
查看事件查看器和设备管理器都没报错,所以没能第一时间确定是它干的。

吗?

但是其实不是它干的,立刻买了 RTL8125B 有线网卡结果发现也会断开。

手头没有交换机,使用另外一台路由器斐讯 K3 不接 wan 口当交换机,AP 和 PC 都直接连接到上面,发现 I225-V 和 RTL8125B 都没有断开。

顺便测了一下 iperf3:

手机到 PC 测速,交换机担当:斐讯 K3 RTL8125B I225-V
TCP 单线程 646 Mbits/sec 549 Mbits/sec
UDP -b 10G 206 MBytes   173 Mbits/sec  0.076 ms  729/150262 (0.49%)  receiver 186 MBytes   156 Mbits/sec  0.096 ms  527/135180 (0.39%)  receiver

那么为什么  PC 和头显都连 Wifi 时没有断开呢?
理论上流量还是要通过路由器兼交换机,可能因为我使用的 Wifi 接入点是一台胖 AP(可以切换为瘦 AP),接入点都是它的客户端时客户端之间通信它能本机转发,不通过路由器/交换机,这点已通过在路由器 tcpdump 抓包和 top 负载证实。这样的话 TP-LINK 胖 AP 真不错,不需要 AC 也能通过商云批量管理。

另外通过小米 AX3600 测速,有长达 7 秒的 0.00 bits/sec,其他设备都未出现过,测速结果不稳定也没 K3 快,已经无力吐槽。
这辈子是告别小米网络设备了。

真、结论:罪魁祸首是小米 AX3600 或魔改,或者其上的 Openwrt 或其上的软件。 正如前言所说,到这里已经懒得深究了,讲究的就是一个换。
还是 X86+AP 靠谱吧,很想换 X86 路由,但是清一色 Intel I226-V 还是不敢买,结果只能先加一台交换机咯。

最后换了 i5-4210H + 16G 工控机,虽然功耗高了点,但有 2 个 Intel I211。
总体性能强劲, 300 Mbps 速度跑 BT 占用为 0%,也不玩 all in boom,太够用了。

让 Cloudflare Tunnel 走代理

你懂的,就不写太详细了。

Cloudflare Tunnel 是一种内网穿透服务,和其他内网穿透的区别在于 Cloudflare Tunnel 会将你直接穿透到 Cloudflare CDN 上。
因此你可以直接使用此服务搭建网站,或者穿透 SSH、远程桌面什么的,而且是免费的。

然而中国大陆到 Cloudflare 的网络质量你也知道的,要么速度慢,要么根本连不上。
于是你肯定会想到让 Cloudlared 走代理,而且还只让 Cloudlared 走代理,不要影响其他的服务。

然而 Cloudflare Tunnel 所用的客户端 Cloudlared 并不支持设置代理,而且官方也不打算支持。
https://github.com/cloudflare/cloudflared/issues/350#issuecomment-1706842883

所以只好自己想办法了:

根据官方文档:https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/deploy-tunnels/tunnel-with-firewall/

cloudflared 通过端口 7844 连接到 Cloudflare 的全局网络。要使用 Cloudflare Tunnel,您的防火墙必须允许通过端口与以下目的地建立出站连接 7844(如果使用quic协议则通过 UDP,如果使用协议则通过 TCP http2)。

Domain IPv4 IPv6 Port Protocols
region1.v2.argotunnel.com 198.41.192.167
198.41.192.67
198.41.192.57
198.41.192.107
198.41.192.27
198.41.192.7
198.41.192.227
198.41.192.47
198.41.192.37
198.41.192.77
2606:4700:a0::1
2606:4700:a0::2
2606:4700:a0::3
2606:4700:a0::4
2606:4700:a0::5
2606:4700:a0::6
2606:4700:a0::7
2606:4700:a0::8
2606:4700:a0::9
2606:4700:a0::10
7844 TCP/UDP (http2/quic)
region2.v2.argotunnel.com 198.41.200.13
198.41.200.193
198.41.200.33
198.41.200.233
198.41.200.53
198.41.200.63
198.41.200.113
198.41.200.73
198.41.200.43
198.41.200.23
2606:4700:a8::1
2606:4700:a8::2
2606:4700:a8::3
2606:4700:a8::4
2606:4700:a8::5
2606:4700:a8::6
2606:4700:a8::7
2606:4700:a8::8
2606:4700:a8::9
2606:4700:a8::10
7844 TCP/UDP (http2/quic)
cftunnel.com1 Not applicable Not applicable 7844 TCP/UDP (http2/quic)
h2.cftunnel.com1 Not applicable Not applicable 7844 TCP (http2)
quic.cftunnel.com1 Not applicable Not applicable 7844 UDP (quic)

实测下来实际走穿透数据的是 region2.v2.argotunnel.comregion1.v2.argotunnel.com

根据上表,要么你把对应的 IP 记下来,要么和我一样直接添加一整段 198.41.192.0/21198.41.200.0/21 这两个段都属于 Cloudflare, Inc. 的 AS13335,或者直接使用 7844 端口。
IPv6 比较麻烦这里就不管了。

所以目标就是让去往 198.41.192.0/21198.41.200.0/21 或 7844 端口的流量走代理。

或者你只让其中一组走代理,以此来保证有一组回退而不至于直接中断。

如果你使用 Wireguard 之类的...,那么只需要将去往 198.41.192.0/21198.41.200.0/21 的流量都导入对应接口就行了,比如 wg0。

如果你有的是“奇怪的协议”,那么你可能会有某种猫,那么它其实是支持 Socks5、Https、TProxy 等入站方式的,
如果在其他设备上,只需要设置允许局域网连接就行了,也支持设置认证。

其中 TProxy 是 Linux 内核提供的功能,如果你了解 TProxy 就会发现,你可以直接把 4 层数据导进去。

所以我们:

因为我的透明代理程序不在本机且不是 Linux 所以需要转换一下,如果你在本机,可以跳过第一步;
或者你的透明代理程序如果也部署在 Linux 上,也许可以直接把流量导入该机的透明代理端口。(存疑,我没试过)

 

0. 在某种猫上启用 Socks5 或 Https 入站,允许局域网访问,必要时可以加上认证,怎么加就自己去看文档了。

1. 在本机安装 GoProxy 并使用 GoProxy 的 sps 功能将 Socks5 或 Https 代理转换成 Iptables 透明代理

详见:https://snail007.github.io/goproxy/manual/zh/#/?id=_617-iptables-%e9%80%8f%e6%98%8e%e4%bb%a3%e7%90%86
也支持设置验证。

例如:

/opt/goproxy/proxy sps --redir -p :7892 -P socks5://....

就是本机监听 7892 为 TProxy 端口,然后转发到 socks5:// 代理。

 

2. 使用 iptables 将发往 198.41.192.0/21198.41.200.0/21 的流量都导向透明代理端口:

iptables -t nat -A OUTPUT -p tcp -d 198.41.200.0/21 -j REDIRECT --to-ports 7892
iptables -t nat -A OUTPUT -p tcp -d 198.41.192.0/21 -j REDIRECT --to-ports 7892

或者把所有去往 7844 的流量都导向透明代理端口,以免日后 Cloudflare 更改 IP:

iptables -t nat -A OUTPUT -p tcp --dport 7844 -j REDIRECT --to-ports 7892

3. 把 cloudflared 调成 http2 模式。

因为不知道为什么,quic 流量好像不可以。

/usr/bin/cloudflared tunnel --protocol http2

4. 重启 cloudflared。

systemctl restart cloudflared.service

5. 搓一个健康检查。

没想到吧,cloudflared 断了以后并不会自动重连。

所以你得搓一个健康检查器,让它来重启 cloudflared。

简单的 Python 健康检查

需要第三方库 requestssmtplib,安装:pip install requests smtplib

systemd 单元:

[Unit]
Description=cloudflared 健康检查
After=network-online.target
Wants=network-online.target

[Service]
TimeoutStartSec=0
Type=simple
ExecStart=/usr/bin/env python3 -u /path/health_check.py
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target

 

python 脚本:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Author: 10935336
# Version: 2024-10-18.1
# Function: 对指定使用 cloudflare 的 url 进行健康检查,若失败则重启 cloudflared
# License: The Unlicense

import sys
import time
import requests
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import subprocess


def send_email(subject, body):
    msg = MIMEMultipart()
    msg['From'] = SMTP_USER
    msg['To'] = ", ".join(TO_EMAILS)
    msg['Subject'] = subject

    msg.attach(MIMEText(body, 'plain'))

    try:
        if SMTP_PORT == 465:
            server = smtplib.SMTP_SSL(SMTP_SERVER, SMTP_PORT)
        else:
            server = smtplib.SMTP(SMTP_SERVER, SMTP_PORT)
            server.starttls()

        server.login(SMTP_USER, SMTP_PASSWORD)
        text = msg.as_string()
        server.sendmail(FROM_EMAIL, TO_EMAILS, text)
        server.quit()
        print("邮件成功发送至: " + ", ".join(TO_EMAILS))
    except Exception as e:
        print(f"发送邮件失败: {e}")


def get_cloudflared_status():
    try:
        result = subprocess.run(['systemctl', 'is-active', 'cloudflared.service'], stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE, universal_newlines=True)
        status = result.stdout.strip()
        return status
    except Exception as e:
        print(f"获取 cloudflared 服务状态时发生错误: {e}")
        return None


def restart_cloudflared():
    try:
        # 检查服务状态
        status = get_cloudflared_status()
        if status == 'activating':
            print("cloudflared.service 处于 activating 状态,尝试停止服务...")
            subprocess.run(['systemctl', 'stop', CLOUDFLARE_SERVICE], check=True, timeout=10)
            print("cloudflared.service 停止成功,等待 5 秒后重启...")
            time.sleep(5)
        elif status == 'inactive':
            print("cloudflared.service 当前处于 inactive 状态,直接启动服务...")

        # 尝试重启服务
        subprocess.run(['systemctl', 'start', CLOUDFLARE_SERVICE], check=True, timeout=10)
        print(f"cloudflared.service 启动成功, {RESTART_INTERVAL_SECONDS} 秒后再次检查状态")

    except subprocess.TimeoutExpired:
        print("启动 cloudflared.service 超时,尝试停止并清理...")
        try:
            subprocess.run(['systemctl', 'stop', CLOUDFLARE_SERVICE], check=True, timeout=10)
            print("cloudflared.service 停止成功")
        except subprocess.TimeoutExpired:
            print("停止 cloudflared.service 超时,服务可能卡住")
    except Exception as e:
        print(f"启动 cloudflared.service 失败,未知错误: {e}")


def check_health():
    retries = 0
    max_retries = 5
    while retries < max_retries:
        try:
            response = requests.get(URL)
            print(f"访问 {URL} 状态码: {response.status_code}")
            if response.status_code == 200:
                print(f"健康检查通过,{INTERVAL_SECONDS} 秒后再次检查")
                retries = 0
                break
            elif response.status_code != 200:
                print(f"状态码 {response.status_code},正在重启 cloudflared... 当前重试第 {retries} 次")
                restart_cloudflared()
                time.sleep(RESTART_INTERVAL_SECONDS)  # 等待x秒后再次检查
                retries += 1
        except requests.exceptions.RequestException as e:
            print(f"请求错误: {e}")
            retries += 1

        if retries >= max_retries:
            print("连续 5 次失败,发送邮件提醒...")
            send_email(f"Cloudflare Tunnel {NAME} 健康检查失败",
                       f"连续 5 次访问 {URL} 失败,请手动检查代理状态。\n注意:为了避免无限重启,本脚本已停止,修复后你还需要重启本健康检查脚本。"
                       f"\n\n本服务是 {SELF_SERVICE}\n代理服务是 {PROXY_SERVICE}")
            sys.exit(0)  # 让 systemd 不认为是错误退出


if __name__ == "__main__":
    # service 设置
    NAME = ''  # 服务名称,仅作提醒使用
    PROXY_SERVICE = 'goproxy-transparent.service'  # 代理服务名称,仅作提醒使用
    SELF_SERVICE = 'cloudflared-healthcheck.service'  # 本服务 service,仅作提醒使用
    CLOUDFLARE_SERVICE = 'cloudflared.service'  # cloudflare service,需要填写正确

    # 发送邮件的配置
    SMTP_SERVER = ''  # 你的SMTP服务器
    SMTP_PORT = 465  # SMTP服务器端口
    FROM_EMAIL = ''
    SMTP_USER = ''  # 你的邮箱
    SMTP_PASSWORD = ''  # 你的邮箱密码
    TO_EMAILS = ['']  # 接收报警邮件的邮箱

    # 健康检查URL
    URL = ""

    INTERVAL_SECONDS = 300  # 每多少秒执行一次健康检查
    RESTART_INTERVAL_SECONDS = 20  # 重启 CLOUDFLARE 后间隔多少秒再次检查

    while True:
        check_health()
        time.sleep(INTERVAL_SECONDS)

另外根据上面的透明代理原理,你可以给本机发出流量都上透明代理,而不影响本机监听的服务。

在 Linux 系统中,主动发起的网络连接(即客户端连接到服务器)使用的端口范围称为临时端口(Ephemeral Ports),这是操作系统动态分配给客户端进程的端口号。这个端口号用于客户端和服务器之间的通信,而不是像你系统上的服务那样绑定到特定端口(如 HTTPS 的 443 端口)。

不同的 Linux 发行版可能对临时端口范围有不同的默认设置。一般情况下,Linux 系统使用的默认临时端口范围为 32768 到 60999。

这个范围可以通过以下命令查看:

cat /proc/sys/net/ipv4/ip_local_port_range

因此你只需要把来自 32768-60999 的流量都重定向到透明代理端口:

iptables -t nat -A OUTPUT -p tcp --sport 32768:60999 -j REDIRECT --to-ports 7892
iptables -t nat -A OUTPUT -p udp --sport 32768:60999 -j REDIRECT --to-ports 7892

就可以不影响本机运行的服务的流量,比如 NGINX 等;而只影响本机发出的流量,比如访问网页等。

Windows 保留 IPv6 地址,但是不设置 DNS

如果你把 IPv6 DNS 设置为手动,但是留空,那么依然会变成自动获取,此时 nslookup 可以看到服务器是 fe80::1

如果你把 IPv6 DNS 设置为无效地址或者 IPv6 表示的 IPv4 地址,比如 ::ffff:127.0.0.1,此时 nslookup 可以看到无法解析,因为 nslookup 没有回退机制,其他程序包括系统调用理论上是有的。

如果你把 IPv6 DNS 设置为一个带 [] 的地址,比如 [::1],那么你会发现,nslookup 此时会使用 IPv4 DNS。
我不知道是 BUG 还是什么的,总之此方法能用。

目前还能用的中国大陆前端静态资源 CDN

2024-10-09 更新

使用公共 CDN 时请务必使用子资源完整性(Subresource Integrity,SRI):
https://developer.mozilla.org/zh-CN/docs/Web/Security/Subresource_Integrity

参考 Polyfill.io 供应链攻击,Staticfile 、BootCDN 供应链攻击:

目前还能用的中国大陆前端资源 CDN

不能用的

  • Staticfile 供应链攻击投毒。
  • BootCDN 供应链攻击投毒。
  • https://www.webcache.cn/ Web缓存网,2024-09-26 日后迁移到香港,相当于没有加速。
  • https://cdn.jsdmirror.com/ 未知,按 JSdelivr 格式请求,但速度很慢。

远程桌面 RDP 或 SMB 等密码就是不对

用的微软账户,死活密码不对。

改过密码,但是已经重新登录过了,还是不对。

runas /u:你的微软账户邮箱 cmd.exe

用这个,让系统重新刷新一下密码,就可以了。

走某种东西 Steam 下载慢 CPU 100% 系统卡顿

此时某种东西的日志会大量刷屏类似内容,可以看到我的 socket 甚至都耗尽了。

time="2024-10-13T15:29:59.4752883+08:00" level=warning msg="[TCP] dial DIRECT (match Domain/xz.pphimalayanrt.com) 127.0.0.1:49159 --> xz.pphimalayanrt.com:80 error: dial tcp 220.163.254.25:80: connectex: Only one usage of each socket address (protocol/network address/port) is normally permitted.\ndial tcp [240e:94c:4400:300::c]:80: connectex: Only one usage of each socket address (protocol/network address/port) is normally permitted.\ndial tcp 106.60.66.25:80: connectex: Only one usage of each socket address (protocol/network address/port) is normally permitted.\ndial tcp 106.60.66.26:80: connectex: Only one usage of each socket address (protocol/network address/port) is normally permitted.\ndial tcp 222.220.249.25:80: connectex: Only one usage of each socket address (protocol/network address/port) is normally permitted.\ndial tcp 182.242.219.7:80: connectex: Only one usage of each socket address (protocol/network address/port) is normally permitted.\ndial tcp 182.242.56.55:80: connectex: Only one usage of each socket address (protocol/network address/port) is normally permitted.\ndial tcp [240e:94c:4c01:100::5]:80: connectex: Only one usage of each socket address (protocol/network address/port) is normally permitted.\ndial tcp 106.60.81.155:80: connectex: Only one usage of each socket address (protocol/network address/port) is normally permitted.\ndial tcp [240e:94c:4000:1400:0:1:b6f2:3807]:80: connectex: Only one usage of each socket address (protocol/network address/port) is normally permitted.\ndial tcp 222.220.249.26:80: connectex: Only one usage of each socket address (protocol/network address/port) is normally permitted.\ndial tcp 220.163.254.24:80: connectex: Only one usage of each socket address (protocol/network address/port) is normally permitted.\ndial tcp [240e:94d:2:100::c]:80: connectex: Only one usage of each socket address (protocol/network address/port) is normally permitted.\ndial tcp 106.60.81.154:80: connectex: Only one usage of each socket address (protocol/network address/port) is normally permitted."

然而开发人员并不觉得是 BUG。

所以只好自己想办法咯,一般我们都用的 Windows 自带的系统代理。

而 Windows 自带的系统代理的绕过是能填域名的,因为是系统自带的代理设置是  HTTP/HTTPS 代理,所以是有域名信息的。

所以就把 Steam 下载域名添加到绕过中吧。

localhost;100.64.*;100.65.*;100.66.*;100.67.*;100.68.*;100.69.*;100.70.*;100.71.*;100.72.*;100.73.*;100.74.*;100.75.*;100.76.*;100.77.*;100.78.*;100.79.*;100.80.*;100.81.*;100.82.*;100.83.*;100.84.*;100.85.*;100.86.*;100.87.*;100.88.*;100.89.*;100.90.*;100.91.*;100.92.*;100.93.*;100.94.*;100.95.*;100.96.*;100.97.*;100.98.*;100.99.*;100.100.*;100.101.*;100.102.*;100.103.*;100.104.*;100.105.*;100.106.*;100.107.*;100.108.*;100.109.*;100.110.*;100.111.*;100.112.*;100.113.*;100.114.*;100.115.*;100.116.*;100.117.*;100.118.*;100.119.*;100.120.*;100.121.*;100.122.*;100.123.*;100.124.*;100.125.*;100.126.*;100.127.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;192.168.*;127.*;10.*;<local>;csgo.wmsj.cn;dl.steam.clngaa.com;dl.steam.ksyna.com;dota2.wmsj.cn;st.dl.bscstorage.net;st.dl.eccdnx.com;st.dl.pinyuncloud.com;steampipe.steamcontent.tnkjmec.com;steampowered.com.8686c.com;steamstatic.com.8686c.com;wmsjsteam.com;xz.pphimalayanrt.com;*.clngaa.com;*.ksyna.com;*.bscstorage.net;*.eccdnx.com;*.pinyuncloud.com;*.tnkjmec.com;*.pphimalayanrt.com