Zero's Blog https://l2dy.sourceforge.io/ zh-CN Wed, 01 May 2024 06:24:00 +0000 Wed, 01 May 2024 06:24:00 +0000 一种曲折的透明代理方式 https://l2dy.sourceforge.io/2024/05/01/a-complicated-tproxy-mechanism.html https://l2dy.sourceforge.io/2024/05/01/a-complicated-tproxy-mechanism.html Wed, 01 May 2024 06:24:00 +0000 Zero 正常的透明代理
  1. 工作在 L3 的 VPN
  2. tun2socks 
  3. Linux 内核的 TPROXY

曲折的透明代理

  1. 支持 UDP 的 SOCKS5 代理软件
  2. 用户空间的 WireGuard 服务端结合 SOCKS5 转发
  3. 安装了 WireGuard 模块的 OpenWRT 路由器

刚好也是三项,但这不是三个方案,是一个方案的三个组件。

听起来似乎完全没必要做这么复杂,但为了利用上唯一能刷 OpenWRT 的低配路由器、不干扰本就复杂的服务器路由,同时保障信道安全、可达,最终扭曲成了这样。

即使你没有这种特殊情况,或许也能用上某个组件就是了,例如在没有 root 的环境下提供 WireGuard 服务。

支持 UDP 的 SOCKS5 代理

这个相对好找,不过建议使用底层为 UDP 且保留了 UDP 不可靠传输特性的代理软件。否则发挥不了 UDP 的优势,性能上可能有负面影响。

用户空间的 WireGuard 服务端

服务端在一台单独的服务器上运行,建议配置成静态 IP。服务器可以通过 DMZ 或 VLAN 方式接入路由器 LAN 口,也可以接入上一层路由、通过 WAN 口通信。

我选择了开源的 Wiretap,好处是运行在用户空间不用动内核,坏处是性能会比原生网络栈差一些,但应该比虚拟机强。我对 Wiretap 进行了轻度的魔改以支持代理,但 ICMP 包的处理上还没完善。 https://github.com/l2dy/wiretap/tree/tproxy

别忘了在防火墙上放行对应的 UDP 端口,否则是连不上的(废话)。

OpenWRT 路由器

有条件的话买一个高配路由器安装上代理软件并配置 TPROXY 是最佳方案。

但如果你坚持使用低内存或闪存空间有限的低配路由器,WireGuard 是 OpenWRT 上最轻量的 VPN 方案之一了。由于 WireGuard 协议不具备混淆功能、特征过于明显,建议仅在本地使用。当然如果信道完全可信,也可以考虑 tun2socks 方案,省下加密的开销。

那么 DNS 怎么办呢?由于 LuCI 不支持给 WireGuard 接口配置 DNS,需要配置全局 DNS 并关闭从 DHCP 获取 DNS 的选项(设置 noresolv '1')。在 WireGuard 接口配置了 0.0.0.0/0 路由后,DNS 也会走 VPN。这个方案的前提是 SOCKS5 代理支持 UDP,但如果不支持的话也可以魔改服务端,把请求转发到本地的可信 DNS。

TCP 层由于 Wiretap 已经在用户空间 ACK 了相关的包,不会像远程 L3 VPN 那样出现 TCP meltdown。但为了 UDP 还是需要合理调整 MTU 值,否则底层可能会把 UDP 包拆分传输,也可能直接丢弃。

参考资料

]]>
1 https://l2dy.sourceforge.io/2024/05/01/a-complicated-tproxy-mechanism.html#comments https://l2dy.sourceforge.io/feed/
使用 HAProxy 将 https 服务反向代理为 http https://l2dy.sourceforge.io/2023/02/23/haproxy-https-to-http.html https://l2dy.sourceforge.io/2023/02/23/haproxy-https-to-http.html Thu, 23 Feb 2023 16:47:00 +0000 Zero 使用 HAProxy 可以将 https 的服务反向代理成 http,这样即使服务本身不好升级也能利用上 TLS 1.3 等更安全、高效的协议。

这里给出一个示例配置,server-template 中 6 为生成的 server 数量。日志输出可以按需调整。

global
  maxconn 10000
  log stderr format iso local7
  ssl-default-bind-options ssl-min-ver TLSv1.3

defaults
  timeout connect 100ms
  timeout client 30s
  timeout server 30s
  mode http
  maxconn 2000

frontend healthz
  bind *:8402
  monitor-uri /healthz

frontend stats
  bind *:8404
  http-request use-service prometheus-exporter if { path /metrics }
  stats enable
  stats uri /
  stats refresh 5s

frontend http-in
  bind *:80
  log global
  option httplog

  use_backend proxy-%[req.hdr(host)],lower]

  default_backend deny

resolvers defdns
  parse-resolv-conf
  accepted_payload_size 8192
  resolve_retries       3
  timeout resolve       1s
  timeout retry         2s
  hold other           1h
  hold refused         1h
  hold nx              1h
  hold timeout         1h
  hold valid           60s
  hold obsolete        30s

backend proxy-g.co
  balance roundrobin
  http-reuse always
  server-template web 6 g.co:443 ssl verify required ca-file /etc/pki/tls/cert.pem check-sni g.co sni req.hdr(host) check inter 16s fastinter 2s resolvers defdns init-addr none

backend deny
  http-request deny
]]>
0 https://l2dy.sourceforge.io/2023/02/23/haproxy-https-to-http.html#comments https://l2dy.sourceforge.io/feed/
YubiKey 禁用触摸输入 OTP 串 https://l2dy.sourceforge.io/2023/01/26/yubikey-disable-touch-otp-code.html https://l2dy.sourceforge.io/2023/01/26/yubikey-disable-touch-otp-code.html Thu, 26 Jan 2023 16:56:00 +0000 Zero 官方建议的禁用方式是将 OTP 输入程序切换到需要长按的 Slot 2,可以使用 YubiKey Manager 或 ykman otp swap 实现。

使用命令行切换后可以通过 info 命令验证是否切换成功。

$ ykman otp info
Slot 1: empty
Slot 2: programmed

注意 macOS 系统下需要给终端 app 开启 Input Monitoring 权限,并关闭 app 的 Secure Keyboard Entry(如有)。

]]>
0 https://l2dy.sourceforge.io/2023/01/26/yubikey-disable-touch-otp-code.html#comments https://l2dy.sourceforge.io/feed/
Linux 4.20+ 开启 BBR TCP 拥塞控制算法 https://l2dy.sourceforge.io/2022/12/27/linux-4-10-tcp-bbr.html https://l2dy.sourceforge.io/2022/12/27/linux-4-10-tcp-bbr.html Tue, 27 Dec 2022 15:57:00 +0000 Zero 参考谷歌提供的文档,对于高负载(如何定义?)的服务器建议同时使用 fq qdisc。

# copy following into /etc/sysctl.d/98-tcp-bbr.conf
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr

普通负载的虚拟机可以直接用默认的 fq_codel qdisc,只配置 tcp_congestion_control

#net.core.default_qdisc = fq_codel
net.ipv4.tcp_congestion_control = bbr

注意对于 qdisc 的修改需要重启服务器生效。

]]>
0 https://l2dy.sourceforge.io/2022/12/27/linux-4-10-tcp-bbr.html#comments https://l2dy.sourceforge.io/feed/
Nginx proxy_pass 502 Bad Gateway https://l2dy.sourceforge.io/2022/08/20/nginx-selinux-connect.html https://l2dy.sourceforge.io/2022/08/20/nginx-selinux-connect.html Sat, 20 Aug 2022 03:22:00 +0000 Zero Rocky Linux 8 上安装 nginx 后对 nginx.conf 进行修改增加了一个 proxy_pass 配置,但用浏览器访问时提示 502 Bad Gateway,也就是连接不上后端服务。照例先怀疑一下 SELinux。

# getsebool httpd_can_network_connect
httpd_can_network_connect --> off

检查 SELinux 配置发现没有给 HTTP 服务主动发起 TCP 连接的权限,用 setsebool 调整后就正常了。

setsebool -P httpd_can_network_connect on
]]>
0 https://l2dy.sourceforge.io/2022/08/20/nginx-selinux-connect.html#comments https://l2dy.sourceforge.io/feed/
AWS Data Transfer Free Tier 范围之外的收费项 https://l2dy.sourceforge.io/2022/08/17/aws-data-transfer-cost.html https://l2dy.sourceforge.io/2022/08/17/aws-data-transfer-cost.html Wed, 17 Aug 2022 15:44:00 +0000 Zero AWS EC2 的入向流量完全免费,出向有一个每月免费 100 GB 的额度,包括 “data transfer out under the monthly global free tier” 和 “regional data transfer under the monthly global free tier” 两种收费项都可以用,后者应该是包含了同 region 的跨 AZ 流量费。

这样看似乎只要不用超这 100 GB 正常的单 AZ、只访问互联网的话使用是不会收费的。但我还是在 Free Tier 没有用完之前就收到了配置的 0% 预算报警邮件。

从 Cost Explorer 按 Usage Type 分组后下载 csv 可以看出收费项是 <使用的region>-<某个未使用的region>-AWS-Out-Bytes。参考 S3 文档可以发现这是从我使用的 region 到一个我没有使用的 region 的数据传输费用。

Figure-2.-Accessing-AWS-services-in-different-Region-1.jpg

[^] 上图来自 https://aws.amazon.com/blogs/architecture/overview-of-data-transfer-costs-for-common-architectures/

从上图可以看出,即使流量通过了 Internet Gateway,到其他 AWS region 的流量还是会按跨 region 流量收费,而这部分是不在 Free Tier 范围内的。这甚至包含了非自己账号下的资源,例如被其他部署在 AWS 上的爬虫扫描和主动调用构建在 AWS 上的第三方服务产生的出向流量。

开启 Cost Allocation Tags 尝试分析流量来源发现确实是 EC2 实例调用某 SaaS 服务时产生的费用,只能避免使用该服务了。使用量很小的前几天还没有出现在账单里,但是预算报警已经提前触发了,此时可以从 Cost Explorer 分析来源及时止损。

其实 AWS 的本意应该是对于跨 region 的流量按比到互联网更低的 $0.01-0.02/GB 价格收费,但由于这部分没有计入 Free Tier 反而增加了成本。想要完全免费使用 Free Tier 就必须避开构建在 AWS 其他 region 上的服务并且用安全组限制只开放服务给特定网段,例如 https://aws.amazon.com/blogs/security/automatically-update-security-groups-for-amazon-cloudfront-ip-ranges-using-aws-lambda/ 这种使用 Lambda 定时更新安全组的方案。

不过话说回来这个价格已经很低了,如果嫌麻烦直接付了也没问题。

]]>
0 https://l2dy.sourceforge.io/2022/08/17/aws-data-transfer-cost.html#comments https://l2dy.sourceforge.io/feed/
Notion 任务看板过滤历史和截止时间过于遥远的任务 https://l2dy.sourceforge.io/2022/08/12/notion-task-board-filter.html https://l2dy.sourceforge.io/2022/08/12/notion-task-board-filter.html Fri, 12 Aug 2022 16:27:00 +0000 Zero 使用组合 filter 可以过滤掉历史已完成任务和截止时间过于遥远的任务,这样可以减少对当前重要和紧急事务的干扰。

notion-task-board-filter.png

P.S. 其中 Last Updated 属性是 Last edited time 类型,值由 Notion 自动维护。

]]>
0 https://l2dy.sourceforge.io/2022/08/12/notion-task-board-filter.html#comments https://l2dy.sourceforge.io/feed/
Prometheus node_exporter 缩减指标上报量 https://l2dy.sourceforge.io/2022/08/02/prometheus-exporter-cost.html https://l2dy.sourceforge.io/2022/08/02/prometheus-exporter-cost.html Tue, 02 Aug 2022 12:47:00 +0000 Zero 虽然时序数据很好压缩导致占用的存储量不多,但公有云上的托管 Prometheus 是按摄入采样数计费的,对于 15s 间隔的采样来说用量很容易超标。

为了控制成本,我们先禁用掉大部分默认导出的指标,然后明确启用需要的采集器。

--collector.disable-defaults --web.disable-exporter-metrics

Uptime

--collector.stat --collector.time (Linux)
--collector.boottime --collector.time (FreeBSD)

CPU

--collector.cpu

MEM

--collector.meminfo

Disk

--collector.diskstats --collector.filesystem (Linux)
--collector.devstat --collector.filesystem (FreeBSD)

Network

--collector.netdev --collector.netstat (Linux)
--collector.netdev --collector.devstat (FreeBSD)

OS

--collector.os
]]>
0 https://l2dy.sourceforge.io/2022/08/02/prometheus-exporter-cost.html#comments https://l2dy.sourceforge.io/feed/
DigitalOcean Rocky Linux 8 默认镜像释放内存 https://l2dy.sourceforge.io/2022/07/01/digitalocean-rocky-low-mem.html https://l2dy.sourceforge.io/2022/07/01/digitalocean-rocky-low-mem.html Fri, 01 Jul 2022 17:14:00 +0000 Zero DigitalOcean 新推出了一款只有 512 MB 内存的 droplet,然而跑个 dnf upgrade 都能触发 Out of memory: Killed process 10365 (semodule)

ps avxf 可以查看进程的内存占用(RSS)。在搜索资料后我发现以下服务可以优化掉,不过要避免 out of memory 还是建议配置 swap,或者换个包管理器更轻量的发行版,例如 Debian。

droplet-agent

即 The DigitalOcean Droplet Agent,可通过 systemctl 关闭,或用 dnf 完全卸载。

dnf remove droplet-agent

sssd

参考 https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html-single/configuring_authentication_and_authorization_in_rhel/index 使用以下命令可切换到最小化认证并关闭 sssd 服务。

authselect select minimal
systemctl stop sssd.service
systemctl disable sssd.service

tuned

参考 https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/monitoring_and_managing_system_status_and_performance/getting-started-with-tuned_monitoring-and-managing-system-status-and-performance 修改 /etc/tuned/tuned-main.conf 配置即可。

daemon = 0

gssproxy

不需要 Kerberos 的话直接卸载也不会有什么问题。 https://github.com/gssapi/gssproxy/blob/main/docs/README.md

dnf remove gssproxy

dnf-makecache

dnf 缓存会定期自动更新,为了保证稳定的内存占用需要禁用掉 dnf-makecache.timer.

systemctl stop dnf-makecache.timer
systemctl disable dnf-makecache.timer

最终效果

# free -h
              total        used        free      shared  buff/cache   available
Mem:          460Mi       103Mi       227Mi       6.0Mi       130Mi       339Mi
Swap:            0B          0B          0B
]]>
0 https://l2dy.sourceforge.io/2022/07/01/digitalocean-rocky-low-mem.html#comments https://l2dy.sourceforge.io/feed/
从 EPEL 安装 strongSwan 配置 IPv6-only VPN https://l2dy.sourceforge.io/2022/06/04/strongswan-ipv6-only.html https://l2dy.sourceforge.io/2022/06/04/strongswan-ipv6-only.html Sat, 04 Jun 2022 16:07:00 +0000 Zero 首先由于 IPv6 VPN 服务器会转发 IPv6 包,需要用 sysctl 开启内核的 IPv6 转发。将以下内容配置到 /etc/sysctl.d 目录下一个 .conf 文件中,并用 sysctl -p xxx.conf 加载或重启服务器。

net.ipv6.conf.all.forwarding = 1

然后我们来安装 strongSwan。 dnf install epel-release 安装上 EPEL 源,然后 dnf install strongswan 就 OK 了。

strongSwan 现已支持 swanctl.conf 新格式的配置文件,文件路径在 /etc/strongswan/swanctl/swanctl.conf,密钥放在 /etc/strongswan/swanctl 对应目录下。下面给出一个示例配置,配置完成后可以通过 systemctl start strongswan.service 启动。

connections {
    ikev2-vpn {
        version=2
        remote_addrs=%any
        local_addrs=%any
        send_cert=always
        pools=pool-subnet-ipv6
        dpd_delay=300s
        children {
            ikev2-vpn {
                local_ts=::/0
                dpd_action=clear
            }

        }
        local-0 {
            certs = cert.pem
            id = @<domain>
        }
        remote-0 {
            auth = eap-mschapv2
            id = %any
        }
    }
}

pools {
    pool-subnet-ipv6 {
        addrs=xxx:8/125
        dns=2001:4860:4860::8888,2001:4860:4860::8844
    }
}

secrets {
    eap-user1 {
        id=user1
        secret="password"
    }
}

authorities {
}

P.S. 带有中间证书的证书文件需要拆分,strongSwan 只会读取证书文件里的第一个 PEM 证书。

]]>
0 https://l2dy.sourceforge.io/2022/06/04/strongswan-ipv6-only.html#comments https://l2dy.sourceforge.io/feed/