惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
aimingoo的专栏
aimingoo的专栏
Microsoft Security Blog
Microsoft Security Blog
NISL@THU
NISL@THU
T
Threatpost
T
The Exploit Database - CXSecurity.com
T
Threat Research - Cisco Blogs
S
Securelist
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
人人都是产品经理
人人都是产品经理
B
Blog RSS Feed
S
Secure Thoughts
MyScale Blog
MyScale Blog
O
OpenAI News
P
Palo Alto Networks Blog
美团技术团队
C
Cyber Attacks, Cyber Crime and Cyber Security
TaoSecurity Blog
TaoSecurity Blog
量子位
L
Lohrmann on Cybersecurity
G
GRAHAM CLULEY
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
T
Tailwind CSS Blog
Know Your Adversary
Know Your Adversary
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Simon Willison's Weblog
Simon Willison's Weblog
宝玉的分享
宝玉的分享
PCI Perspectives
PCI Perspectives
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
C
Cybersecurity and Infrastructure Security Agency CISA
T
Tenable Blog
I
InfoQ
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Microsoft Azure Blog
Microsoft Azure Blog
Recent Announcements
Recent Announcements
S
Security @ Cisco Blogs
S
Schneier on Security
B
Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
The Cloudflare Blog
AWS News Blog
AWS News Blog
IT之家
IT之家
V
Vulnerabilities – Threatpost
The Hacker News
The Hacker News
H
Heimdal Security Blog
I
Intezer
A
Arctic Wolf
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
H
Help Net Security
W
WeLiveSecurity

Jiajun的技术笔记

你好,2026! TiDB 源码阅读(六):TiDB Coprocessor 源码解析 性能优化的核心思想 TiDB 源码阅读(五):索引 TiDB 源码阅读(四):AST、逻辑计划、物理计划 CockroachDB Serverless Architecture podman 无故退出 Cursor Control-L (CTRL-L) Keyboard Shortcuts in Terminal Replace docker with podman Using xmonad with xfce4 A RC script for freebsd frpc 自己动手写一个k8s controller AI 会取代你的(编程)岗位吗? 自建DERP服务器提升Tailscale连接速度(使用Nginx转发) 自动升级Docker容器 再读《程序员修炼之道-从小工到专家》 让浏览器下载文件 再读《软件随想录》/《黑客与画家》/《软技能》 HTTP 压力测试中的 Coordinated Omission 2的补码 编程语言中的 context 是什么? flutter macOS 构建出错 Flatpak 使用小记 Golang CAS 操作是怎么实现的 PostgreSQL 当MQ来使用 Clash 结合 工作VPN 的网络设计 使用 PostgreSQL 搭建 JuiceFS PostgreSQL 配置优化和日志分析 有GitHub Copilot?那就可以搭建你的ChatGPT4服务 窗口函数的使用(以PG为例) 读《为什么学生不喜欢上学》 OpenAI Prompt Engineering 摘录和总结 读《打造真正的新产品》 VueJS 总结 Linux 自动挂载 alist 提供的webdav FreeBSD 使用 vm-bhyve 安装Debian虚拟机 FreeBSD 和 Linux 网卡聚合实现提速 GPT 帮我搞定了时区转换问题 长任务系统如何处理? macOS/Linux 编译 InputLeap 使用开源软KVM - synergy-core 解决 macOS 终端hostname一直变化问题 KVM 共享 Intel 集成显卡 PromQL 备忘 读《格鲁夫给经理人的第一课》 读《打开心智》 为什么要把复杂的联表操作拆成多个单表查询? 红包系统的设计 MySQL Index Condition Pushdown Optimization Go mod 简明教程 OpenWRT 使用 Android/iOS USB 网络 Golang gRPC 错误处理 编写可维护的单元测试代码 OAuth 2 详解(六):Authorization Code Flow with PKCE OAuth 2 详解(五):Device Authorization Flow OAuth 2 详解(三):Resource Owner Password Credentials Grant OAuth 2 详解(四):Client Credentials Flow OAuth 2 详解(二):Implict Grant Flow OAuth 2 详解(一):简介及 Authorization Code 模式 ElasticSearch 学习笔记 三种git流程以及发版模型 错误处理实践 权限模型(RBAC/ABAC) OIDC(OpenID Connect) 简介 任务队列简介 PostgreSQL 操作笔记 使用Drone CI构建CI/CD系统 Golang migrate 做数据库变更管理 使用PostgreSQL做搜索引擎 Nginx 源码阅读(三): 连接池、内存池 Nginx 源码阅读(二): 请求处理 Nginx 源码阅读(一): 启动流程 Go 泛型简明教程 KVM 显卡穿透给 Windows 使用 HTTP Router 处理 Telegram Bot 按钮回调 使用反射(reflect)对结构体赋值 GIN 是如何绑定参数的 你好 2022(2021 年终总结) 用Go导入大型CSV到PostgreSQL 使用 OpenWRT 搭建软路由 使用软KVM切换器 barrier 共享键鼠 SQL 防注入及原理 使用 gomock 测试 Go 代码 gevent不是黑魔法(二): gevent 实现 gevent不是黑魔法(一): greenlet 实现 用 entgo 替代 gorm 应用内使用crontab不是那么方便 单测时要不要 mock 数据库? Sentry 自建指南 用selenium完成自动化任务 用闲置的安卓手机做垃圾电话短信过滤 推荐三个时间管理工具 一次事故反思 当JS遇到uint64:JS整数溢出问题 SQLite3 存储以及ACID原理 Redis源码阅读:pub/sub实现 Redis源码阅读:zset实现 Redis源码阅读:bitmap 位图的运算 Redis源码阅读:set是怎么做交并集运算的? Redis源码阅读:list实现(ziplist, quicklist)
搭建旁路由
Jiajun Huang · 2022-11-20 · via Jiajun的技术笔记

搭建旁路由

有一台机器处于这样的环境:有DNS污染、无法访问外网,而经常又需要下载一些依赖需要外网。但是这是一台老机器,没有多个 网口,因此无法网卡穿透做OpenWRT。那怎么办呢?这个时候,旁路由就可以登场了。

正常情况下,我们手机访问网络,都是这样的链路:

手机 <-> 路由器 <-> ISP(宽带运营商) <-> 网站

加了旁路由以后,会变成这样:

          <----------------------> ISP(宽带运营商) <-> 网站
          |
手机 -> 路由器 -> 旁路由 -
          ^              |
          |-------------->

也就是说,每次流量经过路由器,路由器都会转发给旁路由,然后旁路由再告诉路由器怎么走。这就要求:

  1. 旁路由有一定的数据处理能力:我是直接搭建一台虚拟机,分配4核
  2. 旁路由本身有一个IP:默认情况下,虚拟机都是处于宿主机的一个NAT网络下

1很好解决,加硬件即可。对于2,有两种解决办法:网络桥接(bridge),增加物理网卡。

网络桥接(bridge)

这种方法,需要物理网卡支持,一般来说,有线网卡都是支持的,无线网卡就比较难说了。在Linux中,创建网桥的步骤为:

  1. 断开当前网络
  2. 创建网桥
  3. 将物理网卡设置为网桥的slave
  4. 将虚拟机连接到网桥

命令如下:

$ nmcli connection down Wired # 断开当前网络
$ nmcli con add type bridge ifname br0  # 增加网桥
$ nmcli con add type bridge-slave ifname eno1 master br0  # 将物理网卡设置为网桥的slave
$ nmcli conn up br0  # 启动网桥

然后就是打开 virt-manager ,将网络改为桥接到网桥。

Virt Manager Add Bridge

但是我试过的结果是,启动虚拟机以后,总是要等上1分钟左右,才能连接到网络,控制变量法尝试找过原因,但是都没有找到。 因此,我选择了第二种方法。

增加物理网卡

鉴于桥接网络在我的机器上不太好用,所以我直接用一个USB千兆网卡插到宿主机上,然后 virt-manager 中选择添加USB设备,把 USB网卡穿透给虚拟机进行使用。

设置旁路由

通过上面的设置,虚拟机就可以拿到一个和宿主机一个网段的IP地址了。接下来,我们要做的就是搭建路由系统。我虚拟机里安装的 是Debian。

  1. 下载 clash
  2. 设置 systemd 启动文件
  3. 配置 clash 规则

下载clash,保存至 /usr/local/bin/clash,给予运行权限。新建用户组:

$ useradd -M -s /usr/sbin/nologin clash
$ sudo mkdir -p /etc/clash/

配置好规则:

  1. /etc/clash/iptables.sh 文件,设置各种 iptables 规则。

    #!/usr/bin/env bash
    
    set -ex
    
    # ENABLE ipv4 forward
    sysctl -w net.ipv4.ip_forward=1
    
    # ROUTE RULES
    ip rule add fwmark 666 lookup 666
    ip route add local 0.0.0.0/0 dev lo table 666
    
    # clash 链负责处理转发流量 
    iptables -t mangle -N clash
    
    # 目标地址为局域网或保留地址的流量跳过处理
    # 保留地址参考: https://zh.wikipedia.org/wiki/%E5%B7%B2%E5%88%86%E9%85%8D%E7%9A%84/8_IPv4%E5%9C%B0%E5%9D%80%E5%9D%97%E5%88%97%E8%A1%A8
    iptables -t mangle -A clash -d 0.0.0.0/8 -j RETURN
    iptables -t mangle -A clash -d 127.0.0.0/8 -j RETURN
    iptables -t mangle -A clash -d 10.0.0.0/8 -j RETURN
    iptables -t mangle -A clash -d 172.16.0.0/12 -j RETURN
    iptables -t mangle -A clash -d 192.168.0.0/16 -j RETURN
    iptables -t mangle -A clash -d 169.254.0.0/16 -j RETURN
    
    iptables -t mangle -A clash -d 224.0.0.0/4 -j RETURN
    iptables -t mangle -A clash -d 240.0.0.0/4 -j RETURN
    
    # 其他所有流量转向到 7893 端口,并打上 mark
    iptables -t mangle -A clash -p tcp -j TPROXY --on-port 7893 --tproxy-mark 666
    iptables -t mangle -A clash -p udp -j TPROXY --on-port 7893 --tproxy-mark 666
    
    # 转发所有 DNS 查询到 1053 端口
    # 此操作会导致所有 DNS 请求全部返回虚假 IP(fake ip 198.18.0.1/16)
    # iptables -t nat -I PREROUTING -p udp --dport 53 -j REDIRECT --to 1053
    
    # 如果想要 dig 等命令可用, 可以只处理 DNS SERVER 设置为当前内网的 DNS 请求
    #iptables -t nat -I PREROUTING -p udp --dport 53 -d 192.168.0.0/16 -j REDIRECT --to 1053
    
    # 最后让所有流量通过 clash 链进行处理
    iptables -t mangle -A PREROUTING -j clash
    
    # clash_local 链负责处理网关本身发出的流量
    iptables -t mangle -N clash_local
    
    # nerdctl 容器流量重新路由
    #iptables -t mangle -A clash_local -i nerdctl2 -p udp -j MARK --set-mark 666
    #iptables -t mangle -A clash_local -i nerdctl2 -p tcp -j MARK --set-mark 666
    
    # 跳过内网流量
    iptables -t mangle -A clash_local -d 0.0.0.0/8 -j RETURN
    iptables -t mangle -A clash_local -d 127.0.0.0/8 -j RETURN
    iptables -t mangle -A clash_local -d 10.0.0.0/8 -j RETURN
    iptables -t mangle -A clash_local -d 172.16.0.0/12 -j RETURN
    iptables -t mangle -A clash_local -d 192.168.0.0/16 -j RETURN
    iptables -t mangle -A clash_local -d 169.254.0.0/16 -j RETURN
    
    iptables -t mangle -A clash_local -d 224.0.0.0/4 -j RETURN
    iptables -t mangle -A clash_local -d 240.0.0.0/4 -j RETURN
    
    # 为本机发出的流量打 mark
    iptables -t mangle -A clash_local -p tcp -j MARK --set-mark 666
    iptables -t mangle -A clash_local -p udp -j MARK --set-mark 666
    
    # 跳过 clash 程序本身发出的流量, 防止死循环(clash 程序需要使用 "clash" 用户启动) 
    iptables -t mangle -A OUTPUT -p tcp -m owner --uid-owner clash -j RETURN
    iptables -t mangle -A OUTPUT -p udp -m owner --uid-owner clash -j RETURN
    
    # 让本机发出的流量跳转到 clash_local
    # clash_local 链会为本机流量打 mark, 打过 mark 的流量会重新回到 PREROUTING 上
    iptables -t mangle -A OUTPUT -j clash_local
    
    # 修复 ICMP(ping)
    # 这并不能保证 ping 结果有效(clash 等不支持转发 ICMP), 只是让它有返回结果而已
    # --to-destination 设置为一个可达的地址即可
    sysctl -w net.ipv4.conf.all.route_localnet=1
    iptables -t nat -A PREROUTING -p icmp -d 198.18.0.0/16 -j DNAT --to-destination 127.0.0.1
    

这里需要根据自己的实际情况进行调整。例如我是直接让clash监听了53端口,所以不需要那个将53转发到1053的规则。

  1. /etc/clash/clean.sh 清理iptables文件

    #!/usr/bin/env bash
    
    set -ex
    
    ip rule del fwmark 666 table 666 || true
    ip route del local 0.0.0.0/0 dev lo table 666 || true
    
    iptables -t nat -F
    iptables -t nat -X
    iptables -t mangle -F
    iptables -t mangle -X clash || true
    iptables -t mangle -X clash_local || true
    
  2. /etc/clash/config.yaml clash配置文件

这个就需要你本来就有,或者本来就知道怎么配置了。可以直接从官网抄一下:https://github.com/Dreamacro/clash/wiki/configuration#all-configuration-options

但是注意几点:

  • tproxy-port: 7893 需要设置成和 /etc/clash/iptables.sh 中的一致
  • allow-lan: true 要设置为 true
  • dns 要打开

    # DNS server settings
    # This section is optional. When not present, the DNS server will be disabled.
    dns:
    enable: true
    listen: 0.0.0.0:53
    # ipv6: false # when the false, response to AAAA questions will be empty
    
    # These nameservers are used to resolve the DNS nameserver hostnames below.
    # Specify IP addresses only
    nameserver:
    - 'tls://dns.rubyfish.cn:853'
    - 'tls://1.1.1.1:853'
    - 'tcp://1.1.1.1'
    - 'tcp://208.67.222.222:443'
    - 'tls://dns.google'
    enhanced-mode: redir-host
    fake-ip-range: 198.18.0.1/16 # Fake IP addresses pool CIDR
    

还有一个 systemd service 文件 /lib/systemd/system/clash.service

[Unit]
Description=Clash TProxy
After=network.target

[Service]
Type=simple
User=clash
Group=clash
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW
Restart=on-failure

ExecStartPre=+/usr/bin/bash /etc/clash/clean.sh
ExecStart=/usr/local/bin/clash -d /etc/clash
ExecStartPost=+/usr/bin/bash /etc/clash/iptables.sh

ExecStopPost=+/usr/bin/bash /etc/clash/clean.sh

[Install]
WantedBy=multi-user.target

配置好以后,启动 clash:

$ sudo systemctl enable --now clash

到这里,你的路由器本身就可以提供DNS服务和代理了。

将虚拟机设置为默认网关和默认DNS服务器

在路由器中,将默认网关和DNS服务器,分别改为虚拟机的IP地址,另外,将虚拟机设置为分配一个固定IP(省得后面DHCP IP变化了 还要改配置)。

至此,重连设备,大功告成。

总结

这一篇文章记录了如何配置一个旁路由,比较适合的情况是物理网口不够用,无法直接搭建OpenWRT,而又需要访问外网,配置好以后, 效果其实和OpenWRT软路由一样。只是还需要在路由器里设置一下默认网关,如果路由器不支持更改,就需要在设备上自定义网关,相对 来说会麻烦一些。


ref: