家庭数据中心系列 基于 HTTP 代理的轻量旁路网关搭建:redsocks2 + iptables 实战指南

1 前言

说到我家的科学环境,在经过三次大的优化之后,结构是这样:

image.png

目前这个结构运行良好,如果内网某台设备需要具备”全局”科学的能力,只需要在爱快上的”流控分流”-“分流设置”-“端口分流”中将该设备的源IP地址关联到爱快的wan2口(连接着AC86u的lan口)即可:

image.png


甚至为了应对AC86u故障时特殊情况,还在内网PVE里部署了一个安装了opencalsh的openwrt的虚拟机来作为应急设备:

image.png

详细搭建过程参见文章:软路由系列 爱快+openwrt最佳部署方案探讨(再见吧,旁路由)


然而,现有的方案也存在一些局限性:

  1. 依赖特定硬件的路由器

    当前方案依赖爱快和 AC86u(或者openwrt)这类具备科学上网能力的路由器,而不管是爱快还是具备科学能力的路由器,拥有的家庭都是少数。因此,对于没有这些设备的用户来说,这个方案其实毫无意义,甚至于对我自己来说,如果有一天电信取消了对3拨的支持,我肯定也不会再使用爱快;而如果AC86u路由器坏了,让我再花高价再买个更好的我也未必会愿意,不管是哪种情况,这个方案都会失效。

  2. 很多设备其实只需要”局部”科学上网

其实,对于大部分内网设备来说,”局部”科学上网就够了。例如,我的生产力设备(Mac mini)以及作为 PT 下载机的 NAS,它们并不需要全局科学上网,尤其是对于需要频繁访问国内内容的设备,全局科学反而可能带来副作用(访问缓慢或者机场套餐流量被浪费)。因此,对于这些设备而言,仅在特定场景下需要科学上网,例如通过 Chrome 浏览器访问某些被墙的网站,或者某些需要科学才能正常使用的本地应用(如 GitHub Desktop),而这些需求通过浏览器智能代理插件(如 SmartProxy)或者网络代理工具(如 Proxifier),结合 Apple TV 上Shadowsocks提供的 HTTP 代理功能就可以满足,完全不需要全局科学。

基于上述考量,且考虑到现有的 Apple TV 已通过 Shadowsocks 提供了 HTTP 代理服务(当然,也可替换为Apple TV上其他科学软件提供的代理,或者其他设备上的 HTTP 或 SOCKS5 代理,Apple TV也并非必需),我希望在此基础上,搭建一个不依赖出口路由器、能够独立部署于内网的轻量、稳定、低延迟的旁路网关方案,从而构建一个能覆盖内网全部设备科学上网需求的体系:对于需要”局部”科学能力的设备,直接使用 HTTP 代理接入;而对于少量需要”全局”科学能力的设备,则通过旁路网关转发访问。

在确定了需要搭建旁路网关之后,一个常见的思路是采用科学上网软件,基于透明代理(TProxy)或虚拟网卡(TUN)的方式,实现内网流量的自动转发,这类方案在技术上已经相当成熟,且拥有广泛的社区实践支持。

然而,考虑到我已有稳定可用的 HTTP 代理服务(Apple TV的稳定性还是很让人放心的),若重新部署基于 TProxy 或 TUN 的完整代理体系,不仅增加了配置和维护的复杂度,也未必能带来实质性的优势。因此,我转而思考,能否围绕现有的 HTTP(或 SOCKS5)代理,搭建一个更为简洁、高效、轻量、稳定的旁路网关。

2 承上启下:我对网关的重新定义


本文后续将围绕”旁路网关”展开讨论,而”网关”这个词,在不同的技术语境中往往有着不同的含义。为了避免误解,也为了方便展开后文的分析,我在这里打算对”网关”的含义进行一次更贴近实际使用情境的拆分、梳理和界定。可以说,这是一种带有我个人理解和实战背景的”重新定义”,希望能帮助大家更好的理解构建旁路网关方案时所面对的核心问题。


在网络项目中,”网关”是一个经常被提及却容易被误解的角色。简单来说,一个网关的职责,是接收同一个广播域内设备发出的、目标 MAC 地址是自己的数据帧(L2 层),剥离出其中的数据包(L3 层,即便这些数据包的目标 IP 并不是它自己),然后根据既定策略完成处理或转发动作

而在本文范围内,一个合格的网关,需要具备以下几种能力:

  1. L3 层的数据包识别与接收能力

它必须能够识别并接收那些”目标 IP 并非自己”的数据包。因为对于大多数常规设备来说,如果目标 IP 与自身网卡 IP 不一致,是不会接收该数据包的,除非网卡处于混杂模式或启用了特定的转发机制。网关设备之所以”例外”,正是因为它被设计成要为他人代劳。

  1. 数据包处理决策能力

网关设备需要根据事先设定的策略,对接收到的数据包做出决策:它应该如何处理这个包?

这类策略可能包括:查询路由表决定下一跳、依据规则引擎进行 ACL 判断、应用分流工具判断是否科学等。

一旦做出判断,设备就会将该数据包送入对应的后续处理模块,比如直接路由转发、NAT 映射,或者其他更复杂的中间处理逻辑。

  1. 协议转换能力(中间处理逻辑之一)

某些数据包在处理过程中并不适合直接按原协议转发,而是需要进入特定的”协议转换路径”,以完成跨协议、跨系统的桥接。这在很多实际场景中都很常见:

  • 比如 VoIP 网关,就负责将传统电话网络中的模拟信号(如 PSTN)转换为基于 IP 的语音协议(如 SIP 或 H.323),从而实现传统电话和网络语音通话之间的互通;
  • 又比如 NAT64 网关,用于 IPv6-only 网络环境下,将 IPv6 的请求自动转换为 IPv4 的数据包,以支持访问不具备 IPv6 支持的传统网站。

这些”协议转换型网关”通过承担中间桥接的职责,使原本无法通信的系统实现了”转译式对话”,而这样的转换逻辑,在某些类型的旁路网关中,也会成为不可或缺的一环。

虽然大多数家庭网络中的网关可能并不涉及复杂的协议转换,但一旦要穿越网络协议之间的”语言障碍”,这个能力便变得尤为关键——这也正是本文后续将着重展开的部分。

  1. 数据包的最终转发

完成策略决策与协议处理后,网关需要将数据包发送至”下一站”。

这个下一站的含义,取决于前面的处理路径:

  • 如果是传统路由转发,那可能就是某个 LAN/WAN 网口,伴随 NAT 或路由跳转;
  • 如果是基于策略分流的科学流量,可能是机场的中转服务器;
  • 如果经过了协议转换,那”下一站”可能是本地或远程的 HTTP/SOCKS 代理服务器。

简而言之,网关的任务就是完成”接收 → 决策 → 可选转换 → 转发”这条完整链路,具备了这四项能力,才称得上是一个”真正意义的”网关。

但需要注意的是:

1、识别与处理,只是职责的一部分,性能才是能否胜任的关键

在一些专业场景中,比如企业网络中的三层交换机,数据包的识别与转发通常由专用的 ASIC 芯片来完成,能做到线速处理,效率极高。而在家庭或自建环境中,大多数网关设备(包括旁路方式)依赖的是自身系统的 CPU 来承担这一切:无论是通过 iptables、nftables、ebtables,还是 redsocks2、Clash、tun2socks 等工具,这些流量的处理逻辑都需要 CPU 介入。

虽然这种方式带来了高度的灵活性,但它也对系统资源提出了更高要求:一旦设备性能不足、策略复杂或并发过高,转发能力就可能成为瓶颈,造成高延迟、丢包、甚至全网瘫痪的风险。

2、网关未必只是一台设备,也可能是多个多台设备组成的系统

很多人一提到”网关”,脑子里冒出来的就是一台设备:可能是个软路由,可能是旁路网关。但实际上,网关的职责是”路径的连接者”与”协议的转换者”,而不是”功能都塞进一台设备”。在实际部署中,尤其是在追求灵活性、模块化或高可用性的场景下,网关的功能完全可以拆解成多个角色,由多台设备协同完成。


3 为什么我不直接使用Apple TV作为”旁路网关”?

在上一节中,我之所以要把”网关”这个概念讲清楚,是因为涉及到为什么本文中我不将Apple TV直接作为内网的所谓”旁路网关”的原因,虽然网上很多教程都是理所当然把Apple TV直接作为”旁路由网关”来用的:

image.png

其实,从严格意义上讲,Apple TV 并不具备作为真正”网关”的必要特征:它本质上是一个消费级媒体终端,既不是面向网络转发设计的设备,也没有任何能力接收并处理”目标 IP 不是它自己”的数据包。换句话说,如果你在局域网中把某台设备的默认网关指向 Apple TV,它收到的数据包如果不是发给自己 IP 的,它是不会理会的,更不可能代为转发或代理出去。这一点,在我们前面谈到的”网关必须能转发目标 IP 不是自己 IP 的包”这一核心能力上,Apple TV 其实是不满足的。

但现实中,一些人会发现——在某些条件下,Apple TV 似乎”神奇地”具备了某种流量转发的能力,甚至能作为”代理网关”使用,这其实是因为另一个不太为人所注意的因素介入了:HomeKit 家庭中枢功能:

image.png

image.png

这个功能原本设计目的是为了让 Apple TV 在 HomeKit 网络中,作为控制中心协调一些不具备完整网络配置能力的智能设备(比如 Thread 或低功耗蓝牙设备)访问互联网:当开启家庭中枢功能后,Apple TV 会临时开启一种类似”共享上网”的服务,把目标 IP 不是自己的流量接收下来,再按照本机路由把接收到流量的源地址转换成自己的IP后转发出去(其实就是单LAN口转发+NAT)。如果同时Apple TV上又刚好安装了科学软件,那当局域网中有设备把默认网关指向其接口IP之后,Apple TV的确是可以提供科学能力的。

只不过,这种能力虽然在技术层面上确实能”看起来像是网关”,但本质上仍是为了特定用途临时”放开”的一种机制,稳定性不好说,也无法承担真正网关那种高性能、高吞吐的角色(苹果自己都没有在任何文档中提到过Apple TV在开启家庭中枢功能后还能做网关,总不能是隐藏福利吧~),也有网友其实也意识到了这个问题:

image.png

并且Surge团队也针对这种用法发过警告:
image.png

总之,Apple TV 在开启家庭中枢功能后,确实可以承担部分”旁路网关”的工作,但这只是巧合下的”副业”,并不是它本该承担的角色,因此,”能用”并不代表”适合”,更不意味着”可靠”。

本质上,Apple TV 对其上安装的各类 App(包括科学上网软件)都有不少权限上的限制。这些科学软件的定位,就是为了勉强满足 Apple TV 本机自身的科学上网需求,而不是为了打造一台完整的科学网关。鉴于 Apple TV 上大部分流量以基于 TCP 协议的 HTTP/HTTPS 通讯为主,这些软件能够对外提供一个基础的 HTTP 代理功能,已经算是相当不错了。

一句话总结:Apple TV 作为旁路网关,其实并不是什么正儿八经的方案。真要说的话,它更适合在单设备临时应急时凑合用一下;但如果想覆盖多台设备,甚至长期稳定使用,那还是算了吧 ——不管是性能、可控性,还是稳定性,它和真正的网关比,差距都非常明显。

4 构建轻量、稳定的”旁路网关”

4.1 概述

在家庭网络中,旁路网关虽然不直接承担网络出口的职责,但却扮演着”中转站”的关键角色——它会拦截或接收内网设备发出的流量,并根据特定策略决定这些流量应被发往何处。而在这一过程中,真正发挥作用的是两类核心工具的配合:网络流量转发工具(如 iptables、nftables)和代理协议转发器(如 redsocks2、tun2socks)。

前者负责”把流量带进来”,决定哪些流量需要被截获并重定向;而后者则负责”如何处理这些流量”——可以是将原始网络请求转换成 HTTP 或 SOCKS 等代理协议格式后交给上游代理,也可以直接将流量交由本机上的科学类程序(如 Clash、Shadowsocks)进行进一步处理。理解这两类工具的职责分工与协作方式,是设计一个高效、稳定、易于维护的旁路网关方案的核心所在。

本部分内容将围绕这两类工具的功能特点、常见选项及适配场景逐一展开分析,最终选出最适合本文使用情境的组合方案。


在我以往的文章中,曾明确表达过对传统 OpenWRT 实现的”单臂旁路由”模式的保留意见,尤其是那种把内网设备默认网关直接指向 OpenWRT 的 WAN 口的做法,虽然部署简单,但问题却不少:一旦 OpenWRT 故障,整个网络就断;OpenWRT 会消耗不必要的性能处理大量原本无需”科学”的直连流量;和主路由之间的 NAT 协调、端口映射也容易出问题。

类似的,Apple TV 来做所谓的”旁路由”网关,本质上也是采用类似的思路:让内网设备的全部流量经过 Apple TV 上安装的代理工具进行处理(最关键还是依靠”家庭中枢”功能提供的附带能力)。这种方式看上去新鲜,实际不过是把 OpenWRT 换成了 Apple TV 而已,技术上的短板、单点故障、可控性差等问题依旧存在。

所以,我想特别强调一点:本文所讨论的”旁路网关”概念,和网上广泛流传的”旁路由”教程,根本不是一回事:尽管名字和部署方式相似,但结构、思路、目标完全不同。

我所说的”旁路网关”,是一种专为”代理转发”场景设计的中转角色:它并不负责提供 NAT 或作为网络出口,而是专注于将接收到的所有外部访问流量(通过默认网关或策略路由导入)统一接收并转化为代理协议(如 HTTP、SOCKS)请求包,再转发给上游代理服务器

听起来这似乎和传统”旁路由”没什么不同——毕竟,它也在接收所有需要上网的流量。但真正的区别,在于它的职责清晰且专一,不参与不必要的 NAT、流控、DNS 劫持等复杂网络功能,因而在结构上更轻、更稳定,性能开销也更集中和可控

换句话说,它不是一个”什么都想管”的多功能路由器,而是一个只负责转发代理流量的精简型节点。你可以把它理解为一个协议翻译器——流量进来,它只做一件事:翻译成代理协议,然后立刻转交给远端代理服务器处理,不缓存、不分析、不决策,整个过程干净利落、毫不拖泥带水。

也正因为职责单一、实现简单,所以它对运行设备的性能要求非常低。而在这种”以简驭繁”的架构下,它依然可以带来相当可观的科学上网性能,适合追求稳定、高效转发的用户部署使用。

这样的节点,可以部署在一台 LXC 容器或者轻量虚拟机上运行,与主路由进行解耦。主路由依旧承担整个网络的核心控制与流量调度职责,而旁路网关节点仅为少量需要全局科学能力的设备服务。这种解耦设计不仅提升了代理链路的灵活性与可控性,也在多数情况下避免了因节点异常导致整个网络核心功能受损的风险——当然,对于将旁路网关节点配置为默认网关的终端设备而言,仍可能因其失联而出现访问异常,但这类影响通常局部可控,不会波及全局

所以,本文并不是为”单臂旁路由”翻案,而是基于更清晰的架构理念与工具组合,构建一个更现代、更适配实际需求的旁路网关方案


4.2 网络流量转发工具介绍

4.2.1 概述

在之前的内容中,我们讨论了”网关”作为网络流量中转站所具备的各项能力:就是”将目标 IP 并非自己的数据流接收下来,按照预先约定的决策进行判断后,转交给后续的功能模块(如协议处理器)处理,再经过某种方式转发出去。而整个”从数据包接收到协议转换器之前”的过程,核心就落在了系统的流量转发工具上(对应网关能力的第1、2点)。

对于基于 Linux 的系统而言,网络流量的转发、重定向、放行等操作,通常都交由内核中的 netfilter 框架来完成。而用户通过命令或脚本与 netfilter 交互的接口,主要有两个:iptables 和 nftables

这两者的目标类似,都是用于制定复杂的流量处理规则,但风格、语法和适用年代略有不同。在实际部署旁路网关时,我们只需配置少量规则,就能实现对目标设备流量的截获与重定向,因此并不需要深入研究其全部机制。但理解它们之间的区别,以及选择其中一个工具的理由,仍然是非常必要的。

这一章我们将简单介绍它们各自的背景、特点以及使用建议,帮助你在部署自己的网关转发规则时做出合适的选择。

4.2.2 iptables:老牌但仍广泛使用的流量管控工具

iptables 可以说是大多数人接触 Linux 网络控制的第一站。它自 Linux 2.4 内核开始被广泛使用,通过四大”表”(filter、nat、mangle、raw)和五条”链”(INPUT、OUTPUT、FORWARD、PREROUTING、POSTROUTING)来管理网络流量的生命周期。

它的语法虽然偏命令式、不太友好,但资料多、社区成熟,尤其在 Debian、Ubuntu 等发行版中,即便到了今天默认依然使用的是 iptables,所以在很多实际部署场景下,继续使用它是最简单直接的方案。

如果你在使用较老版本的 LXC、Docker 基础镜像,或者想用最少折腾完成任务,iptables 完全可以胜任你对流量重定向和转发的需求。

4.2.3 nftables:面向未来的新一代框架

随着内核的发展,iptables 的模块化和规则扩展变得越来越复杂,最终催生了 nftables 这个更现代的继任者。它自 Linux 3.13 起被引入,旨在统一和简化防火墙管理。

与 iptables 相比,nftables 提供了更一致的语法、结构化的数据支持、以及内置调试工具。更重要的是:它是未来 netfilter 体系的主力方向。

许多新发行版(比如较新的 Debian、Fedora、Arch Linux)已默认启用 nftables,而 iptables 则在底层通过 iptables-nft 兼容层间接调用 nftables,也就是说你表面在写 iptables,实际内核走的却是 nftables 的规则。

不过,也正因为这个兼容层的存在,在某些系统上同时使用两者可能出现规则混乱的问题。如果你打算长期维护这套转发规则,且系统默认支持良好,建议直接上 nftables。

4.2.4 我的建议

对于旁路网关这样”功能明确、规则简单”的场景,两者的差距并不明显。实际选择时,不妨以这条原则为准:

  • 系统默认提供哪个,就用哪个。
  • 如果你对语法不熟,网上教程多的那一个通常是 iptables,适合快速落地。
  • 如果你希望未来能灵活扩展更多控制规则,或者你使用的是较新的系统环境(比如 Debian 12、Ubuntu 22.04 以上),可以直接选择 nftables。

4.3 代理协议转发器介绍

4.3.1 概述

在前面的章节中,我们已经通过流量转发工具(如 iptables/nftables)将接收到的数据包截获并可以重定向到本地或远程的某个端口,但这还只是第一步。接下来,必须有一个组件来接收这些原始的 TCP/IP 流量,并将它们转换为上游代理服务器可以理解的代理协议(如 HTTP、SOCKS5),这个组件,就是所谓的代理协议转发器(对应网关能力的第3点)。

4.3.2 redsocks2

redsocks 是最早期的一个流量转发工具,它的设计目标就是简单直接:监听一个本地端口,接收 TCP 流量,把它重新打包为代理协议流量(支持 HTTP CONNECT、SOCKS4/5),然后发送到指定的上游代理服务器。

而我们这里更关注的,是基于 redsocks 魔改出来的 redsocks2(其实还是叫redsocks,只是为了区分习惯性称呼为redsocks2),它在原版基础上做了很多增强,比如:

image.png

注1:需要注意的是,redsocks2 是社区自发维护的,并非官方正式发布的版本,但在很多实际项目中(特别是旁路网关类项目)已经成为事实标准,其github官方地址为”https://github.com/semigodking/redsocks“。

注2:如果你使用的是仍支持 Shadowsocks 协议的代理服务,redsocks2 也可以直接作为客户端连接上去,无需额外搭建本地代理程序,这是它内置的一个特色能力。但需要说明的是,Shadowsocks 作为一个早期设计的协议,如今在实际使用中逐渐被视为”老协议”:一方面,它的协议特征较为明显,容易被识别与干扰;另一方面,在连接稳定性和抗干扰性方面,也逐渐难以满足更加复杂的网络环境需求。因此,当前大多数高可用代理方案,已经转向了更现代的协议栈,比如 VLESS、trojan、Reality 等。所以本文依然聚焦在 redsocks2 作为协议转发器的角色,主要与现成的 HTTP 或 SOCKS5 代理配合使用,而非将其作为”shadowsocks”客户端使用。

4.3.3 2. tun2socks

tun2socks 是另一种流量转发思路,它的核心不同在于:它并不单独处理 TCP/UDP 流量,而是模拟出一个虚拟的 TUN 设备,把所有流量重定向到这个虚拟网卡,再在内核协议栈之前直接做 SOCKS5 代理转发。

tun2socks 的特点:

  • 主要基于 SOCKS5 协议(部分版本支持 HTTP CONNECT)
  • 可以透明代理整个设备(比如 Android、OpenWRT)
  • 对 UDP 支持较好(取决于实现版本)
  • 性能中等,但架构简单

通常,tun2socks 适合需要整机透明代理的场景,比如在手机、路由器等设备上直接通过 TUN 设备出口代理。而如果只是想拦截特定端口/规则流量,tun2socks 有些”用大炮打蚊子”的味道。

4.3.4 我的建议:redsocks2

这次搭建旁路网关,其实我的目标很明确:希望它能轻量一点、稳定一点,关键是部署简单、后续好维护。redsocks2 正好就满足了这些需求。它的性能一直很靠谱,跑起来不容易出幺蛾子,特别适合放在这种”插电即用”的中继节点上。而且配置很直观,不需要额外折腾 TUN 虚拟网卡,也不用修改路由表,省了不少麻烦。更巧的是,它支持多种上游代理协议,尤其是 HTTP,这点正好能和我 Apple TV 上跑的 Shadowsocks 提供的 HTTP 服务配合使用。

综合来看,redsocks2 算是最适合当前这个旁路网关场景的方案了:够轻、够稳,也够省心。

4.4 最终转发目的地

在本文所讨论的”旁路网关”场景中,代理协议转发器(本文中使用的是 redsocks2)的任务,是将由 iptables 或 nftables 拦截并重定向过来的流量,根据实际配置的上游代理类型进行协议转换,然后再转发到上游代理服务器(网关能力第4点)。

至于上游代理服务器的类型,并没有强制要求。你可以根据自己的网络环境选择 HTTP 代理或 SOCKS5 代理,都可以。拿我自己的情况举例:因为家里有一台 Apple TV,并且安装了 Shadowrocket,它正好可以提供一个可用的 HTTP 代理,所以我就直接用了这个现成的出口。如果你自己有一个稳定的 SOCKS5 节点,那也完全没问题。对于 redsocks2 来说,配置上只需要指定正确的代理协议和地址即可,两者没有本质区别。

需要注意的是:iptables/nftables、redsocks2、以及最终的代理服务本身,并不需要部署在同一台设备上(当然部署在同一台设备上也完全没问题),你可以根据自己的实际情况设计最合适的结构,比如:

  • 我自己的部署方式,是将 iptables/nftables 和 redsocks2 一起部署在一个 LXC 容器中
  • 而 Apple TV 上单独运行的 Shadowrocket 提供 HTTP 代理,作为最终的出口

这种架构解耦清晰,维护简单,如果哪一个环节故障,也更方便定位和替换。总之,旁路网关的实现方式没有固定答案,关键是根据自己网络环境和设备能力,做出最稳妥、最省心的部署。

5 部署redsocks2

5.1 环境描述

由于HTTP代理是现成的(Apple TV上Shadowrocket提供),所以我主要需要搞定redsocks2即可,最佳性能表现就是使用LXC来部署redsocks2。

我的PVE上虽然有不少运行着的LXC,但是都各有用途:

image.png

想了一下,还是再单独新建一个debian的LXC来部署redsocks2,iptables直接就用这个LXC上的就成,直接拦截流量然后重定向给本地的redsocks2,简单省事:
image.png

注1:LXC的具体新建步骤我之前的文章中已经写过,这里就不再重复了,不清楚的朋友可以参看文章”docker系列 使用LXC基于Turnkey-gameserver架设我的世界(Minecraft)基岩版服务器“。

注2:redsocks2 LXC并不需要太多资源,比如CPU核心最低1-2个就差不多了,内存256兆或者512兆足以,实际情况大家根据自己家里对旁路网关的实际使用度而定。

注3:我是因为本来就有PVE,所以使用了LXC,实际上Ubuntu / Debian可以直接裸机或者LXD,Alpine Linux / Arch / Gentoo也原生支持LXC,QNAP的NAS还可以使用Linux Station来运行,总之选择适合自己的办法就行。

注4:虚拟机也是一样的,只不过相比LXC,虚拟机消耗的资源多了不少,我觉得不太划算而已,对于不支持LXC的虚拟平台直接使用虚拟机就行。

注5:debian系统的初始化可以参看文章”debian系列 系统常规初始化步骤整理“。

5.2 安装redsocks2

1、安装依赖

apt update 
apt install -y build-essential libevent-dev libssl-dev git pkg-config

解释一下每个包的作用:

  • build-essential: 包含 gcc, make 等基本构建工具。
  • libevent-dev: redsocks 的主要事件驱动库依赖。
  • libssl-dev: OpenSSL 的开发包,提供加密支持。
  • git: 如果你还没 clone 代码就会需要。
  • pkg-config: 有些 makefile 会通过它来查依赖版本和编译参数。

为避免后续因功能缺失或编译失败而陷入繁琐排查,我选择一次性启用 redsocks2 的所有模块(主要是怕编译出错~)。

2、克隆源码并编译

git clone https://github.com/semigodking/redsocks.git
cd redsocks
make

3、 确认 gcc 和 make 已安装

gcc --version
make --version

如果没安装:

apt install build-essential

4、编译

如果直接运行make命令进行编译,默认会支持shadowsocks协议以及不支持HTTPS代理。对于我的内网环境而言,redsocks2只需要配合HTTP代理(或者socks5代理)使用即可,所以并不需要支持shadowsocks协议,同时也并不需要HTTPS代理,所以只需要运行以下命令即可:

make DISABLE_SHADOWSOCKS=true

如果同时还想支持HTTPS代理,只需要运行以下命令:

make DISABLE_SHADOWSOCKS=true ENABLE_HTTPS_PROXY=true

最终编译成功:

image.png

编译成功后会生成一个名为redsocks2的可执行文件,可以用命令查看:

ls -lh redsocks2

输出如下:

image.png

如果能正常打印帮助信息即可正常使用:

./redsocks2 -h

输出如下:

image.png

注:我不推荐保留 shadowsocks 功能模块,因为这会引入额外的加密库依赖(如 libsodium、mbedtls),增加编译复杂度和出错几率,尤其在你并不打算实际用它的前提下,完全没有意义(开始我还想保留shadowsocks功能,结果把我折腾惨了,后来只能放弃了~)。

5.3 创建”redsocks2.conf”配置文件

安装完成后,redsocks2需要创建配置文件”redsocks.conf”,假设代理服务器的地址是192.168.1.1,HTTP代理服务端口是8080,SOCKS5代理端口是1080,那么配置文件内容如下:

base {
    log_debug = off;
    log_info = on;
    log = stderr;
    daemon = off;
    redirector = iptables;
}

redsocks {
    // 监听本地 TCP 流量
    bind = "0.0.0.0:12345";
    // HTTP 代理服务器
    relay = "192.168.1.1:8080";
    type = http-connect;
    login = "";
    password = "";
}

redudp {
    // 监听本地 UDP 流量
    bind = "0.0.0.0:12346";
    // 代理服务器是 socks5(要求支持UDP)
    relay = "192.168.1.1:1080";
    type = socks5;
    login = "";
    password = "";
    // 必填,用于 REDIRECT 模式
    dest = "8.8.8.8:53";
    udp_timeout = 30;
    udp_timeout_stream = 180;
}

配置说明:

  • redsocks 段:负责 TCP 流量的代理转发。
  • redudp 段:负责 UDP 流量的代理转发。
  • bind = “0.0.0.0:12345″:监听 LXC 容器的所有网卡的12345端口的TCP请求
  • relay = “192.168.1.1:8080”::这里是HTTP代理的地址和端口
  • type = http-relay:说明目标代理是一个 HTTP 代理。
  • bind = “0.0.0.0:12346″:LXC 容器的所有网卡的12346端口的UDP请求。
  • relay = “192.168.1.1:1080”::这里是SOCKS5代理的地址和端口
  • type = socks5:说明目标代理是一个 SOCKS5 代理。
  • dest = “8.8.8.8:53” 是 UDP 模块需要指定的目标地址和端口,即使只是中转用途,也必须填,这两个值在你的实际流量中不会被使用,只是启动 redudp 所需。

注1:redsocks.conf配置文件和redsocks2可执行文件都就在redsocks目录下。

注2:个人建议,使用redsocks2搭建的旁路网关支持TCP协议一般也足够了,如果要使用redudp段来代理UDP协议,必须使用SOCKS5代理,且该SOCKS5代理必须支持UDP协议(并非所有SOCKS5代理都支持UDP协议,比如merlinclash提供的SOCKS5代理默认就是不支持UDP的,从这个角度来说,redsocks2虽然支持UDP协议的代理,但是真要使用起来还是有所限制的,从这个角度来讲,Proxifier是真牛逼)。

注3:至于 DNS,并不需要指向旁路网关,还是建议直接指向主路由(需要主路由配置DNS劫持)。如果是指向常用的国内 DNS 服务器而主路由又没有配置DNS劫持,那么在这种旁路网关模式下,则需要在旁路网关上配置适当的iptables和ebtables规则将DNS请求重定向到主路由(见文章后面iptables部分)。

5.4 运行redsocks2

在redsocks目录下,直接运行以下命令即可:

./redsocks2 -c redsocks.conf

注1:”-c”参数是指定redsocks2启动时关联的配置文件。

5.5 设置redsocks2开机自启

1、创建 systemd 服务单元文件

vim /etc/systemd/system/redsocks2.service

将以下内容粘贴并保存(以我的环境为例,我是直接git redsocks2到root目录下):

[Unit]
Description=Redsocks2 Proxy Gateway
After=network.target

[Service]
Type=simple
ExecStart=/root/redsocks/redsocks2 -c /root/redsocks/redsocks.conf
User=root
Group=root
WorkingDirectory=/root/redsocks
Restart=always
RestartSec=3

[Install]
WantedBy=multi-user.target
  • ExecStart: 设置为你实际执行 redsocks2 的命令,确保路径正确。
  • WorkingDirectory: 设置为运行 redsocks2 所在的目录,确保 redsocks.conf 配置文件也在正确的路径。
  • User 和 Group: 用来指定 redsocks2 应该以哪个用户和组来运行,避免使用 root 用户运行(不要学我),你可以为它创建一个专门的用户(比如 redsocks)。
  • Restart=always: 如果 redsocks2 意外退出或崩溃,它会被自动重启。
  • RestartSec=3: 进程崩溃后 3 秒钟重启。

2、重新加载 systemd 配置并启用服务

systemctl daemon-reload
systemctl enable redsocks2.service

3、启动 redsocks2 服务

systemctl start redsocks2.service

4、检查服务状态

systemctl status redsocks2.service

正常的话显示如下:

image.png

6 启用内核IP转发功能

在 Linux 系统中,net.ipv4.ip_forward 控制着内核的三层转发能力。默认设置为 0,禁止 IP 包在不同接口之间转发。如果希望设备作为路由器、旁路网关或任何中转节点使用,必须将其打开,否则即便配置了iptables的 NAT (如 SNAT、DNAT)或 REDIRECT 规则,数据包仍然只能本地处理,无法完成转发链路。

临时启用方法:

echo 1 > /proc/sys/net/ipv4/ip_forward

为了在系统重启后保持生效,应同步修改 /etc/sysctl.conf:

vim /etc/sysctl.conf

找到以下这行:

#net.ipv4.ip_forward=1

去掉注释,并保证是 =1:

image.png

然后执行:

sysctl -p

注:未启用 IP 转发是旁路代理搭建中最常见的隐藏问题之一,务必在调试阶段优先确认。

7 iptables的配置

以下是适配文章前面示例redsocks2.conf的iptables配置:

# 创建一个新的 chain
iptables -t nat -N REDSOCKS

# 排除本地回环接口(lo)上的流量
iptables -t nat -A REDSOCKS -i lo -j RETURN

# 排除目标地址是本机自身 IP(假设本机IP是x.x.x.x)的流量
iptables -t nat -A REDSOCKS -d x.x.x.x -j RETURN

# REDIRECT 所有其他 TCP 流量到本地 12345 端口
iptables -t nat -A REDSOCKS -p tcp -j REDIRECT --to-ports 12345

# REDIRECT 所有其他 UDP 流量到本地 12346 端口(可选,用于redudp)
iptables -t nat -A REDSOCKS -p udp -j REDIRECT --to-ports 12346

# 应用 REDSOCKS 规则到 PREROUTING(入口数据包)
iptables -t nat -A PREROUTING -p tcp -j REDSOCKS
iptables -t nat -A PREROUTING -p udp -j REDSOCKS

------------------------------------------------------------------------------
如果客户端的DNS指向公网DNS,才需要配置以下两条规则:

# 把所有 UDP 53 DNS 查询流量转发回主路由(假设主路由mac地址是00:11:22:33:44:55)
ebtables -t nat -A PREROUTING -p IPv4 --ip-proto udp --ip-dport 53 -j dnat --to-destination 00:11:22:33:44:55

# 对转发到主路由的DNS查询包进行源地址NAT,确保DNS响应能返回旁路网关(假设旁路网关的IP是 x.x.x.x)
iptables -t nat -A POSTROUTING -p udp --dport 53 -j SNAT --to-source x.x.x.x

提问:为什么客户端DNS是指向公网DNS时,需要在旁路网关上配置最后两条规则(ebtables和iptables)?要回答这个问题需要一点点网络基础。


可以使用如下命令显示旁路网关中带有行号的iptables规则列表,方便你定位某个特定的规则。:

iptables -t nat -L --line-numbers

我这里显示如下:

image.png

可以使用如下命令按表查看旁路网关中ebtables规则列表:

ebtables -t nat -L

我这里显示如下:

image.png

其实就是将旁路网关所有收到的TCP流量重定向到本地的12345端口;将目标端口为UDP 53的流量直接转发到主路由器并将UDP包源地址NAT成旁路网关的地址;将其他所有收到的UDP流量重定向到本地的12346端口(配置了UDP代理的前提下,反正我是没有配置的),很简单,至此,旁路网关搭建完毕,所有需要全局科学能力的设备只需要将默认网关指向redsocks2部署设备的IP地址即可(DNS服务器维持原来的设置即可,非要指向旁路网关也没问题,只是有点多此一举)。

注1:iptables 和 ebtables 的配置,默认只是临时生效的,如果你不手动保存配置,重启后它们都会消失(因为 Linux 的网络堆栈初始化时不会自动还原你临时加的规则)。方法有几种,大家自己搜教程吧,懒得写了,不是本文的重点。

注2:实际部署时,为了兼顾简洁性和兼容性,我选择了不引入 ebtables,只通过 iptables 配置 TCP 透明代理,同时让 DNS 解析指向主路由,这样旁路由可以完全不处理UDP流量,简化了整体架构,可以放弃使用ebtables,好处在于运维更方便,只需要保存iptables的配置即可(可以使用iptables-persistent自动完成开机自动导入iptables配置)。

注3:虽然可以通过 ebtables 修改目标 MAC 地址,再结合 iptables 做 SNAT,从而让旁路网关完整接管设备发出的 UDP 流量,避免路由冲突,但这种方案在遇到像 Tailscale、ZeroTier 等自建隧道网络的应用时,仍然可能出现兼容性问题。这类应用通常依赖本地路由表或虚拟网卡管理出站流量,旁路网关的中间劫持反而会破坏其正常连接。因此,在部署旁路网关时,建议接入设备尽量保持干净,不安装此类特殊应用,以保证旁路方案的稳定性和一致性。

8 总结

本文介绍了如何使用 redsocks2 搭配 HTTP 代理,搭建一个轻量、稳定且性能优秀的旁路网关。严格来说,redsocks2 + HTTP 代理构建的这种方案,并不能处理所有类型的网络流量,它本质上是一个针对 HTTP/HTTPS 流量的透明代理网关。不过在大多数日常办公或家庭环境,普通用户的 TCP 流量中HTTP/HTTPS 协议占比通常高达 80%~90%。因此,即便这种方案只针对 HTTP/HTTPS,依然能够覆盖绝大部分科学上网需求,效果上接近于”全局代理”。

这种方式的优点在于部署简单、资源占用低,适合已有主路由框架、但希望对部分设备进行全局科学的用户,尤其是为无法或不愿折腾 TUN/TProxy的朋友,能提供一个易于维护、迁移和恢复的解决方案(特别是有Apple TV的前提下,不过需要注意的是:Apple TV上所有科学上网软件都只对外提供HTTP代理)。

当然,这种方案也并非完美,例如,UDP 流量依赖于支持特殊转发的 SOCKS5 代理,而很多TCP 应用(SSH、SMTP、IMAP、MySQL、Redis、RDP、WebSocket等)对 HTTP 代理的兼容性也不理想,最关键是还需要一个现成的HTTP代理。


其实专门的科学软件对UDP代理支持一样是有条件的,比如Merlinclash的说明:

image.png

image.png

可怜我的AC-86U~,这也是我研究旁路网关的原因之一:以后惹毛了我干脆直接全面转向科学旁路网关方案,反正现在也不支持,对我完全没影响~。


如果你对旁路网关的透明代理能力有更高要求(例如希望旁路 UDP 协议,或实现 TCP 全流量透明转发),可以在本文方案的基础上进一步扩展,结合 tun2socks 等工具,将已有的 HTTP/SOCKS5 代理流量转化为透明代理访问,实现更完善的流量接管。而如果希望构建一套功能更完整、控制更细致的透明代理体系,也可以考虑使用 sing-box、Hysteria 等现代代理平台,重新搭建一套独立的代理环境。

但即便不进行扩展,本文所示的 redsocks2 + HTTP 代理模式,也已经在可用性、稳定性与简洁性之间取得了良好平衡,是在家用网络中部署旁路网关时非常值得优先尝试的方案,已经能够满足绝大多数人的需求了。

下面是一些常见应用在旁路网关模式下,对redsocks2上级代理是HTTP代理或者SOCKS5 代理的支持情况一览,一般人是完全足够的:

应用 上游为 HTTP 代理 上游为 SOCKS5 代理 备注说明
apt 支持 支持 发出的为 HTTP/HTTPS 请求,均可被透明代理
curl 支持 支持 完全兼容透明代理,无需额外参数
wget 支持 支持 行为类似 curl,部分版本对 SOCKS 支持不稳定但不影响旁路模式
git(HTTPS 协议) 支持 支持 发出 HTTPS 请求,可被 redsocks2 接管
git(SSH 协议) 不支持 不支持 发出为 SSH 协议,不属于 HTTP 流量,无法透明转发
ssh 不支持 不支持 同上,SSH 协议无法被 redsocks2 处理
浏览器(如 Chrome) 支持 支持 基于 HTTP 协议通信,可完全透明代理,体验良好
Electron 应用(如 VSCode) 支持 支持 使用系统网络栈,行为与浏览器类似,透明代理生效

为了直观表现一下本文所采用的「redsocks2 + HTTP/SOCKS5代理」方案,与更常见的「科学软件 + TProxy/TUN透明代理」方式之间的优劣势,我也做了一下对比:

对比项目 redsocks2 + HTTP/SOCKS5代理 科学软件 + TProxy/TUN透明代理
部署复杂度 较低,仅需配置流量转发和基本防火墙规则 较高,需要深入理解 TProxy/TUN 机制及复杂防火墙策略
依赖组件 只需已有 HTTP/SOCKS5 代理,无需额外科学软件运行 需要部署和长期维护完整的科学软件系统
系统资源占用 极低,redsocks2 本身非常轻量,资源开销可忽略 较高,科学软件运行本身带来一定 CPU 和内存消耗
功能覆盖 支持 TCP 流量旁路,满足绝大多数科学需求 支持 TCP+UDP 流量全透明旁路,功能更全面
稳定性 极高,组件少,转发逻辑简单,出错概率低 较低,运行组件多,长期稳定性依赖于科学软件
排错难度 低,排查路径清晰,抓包分析简单直接 高,涉及防火墙、路由表、软件内部机制,问题复杂
环境适应性 强,只需 HTTP/SOCKS5 代理即可运行,适配多种内网环境 一般,需较稳定、开放的 Linux 环境,适配性受限
运维成本 极低,部署后长期几乎免维护 较高,需要关注科学软件升级、规则更新和异常处理

可以看出,「redsocks2 + HTTP/SOCKS5代理」在保持可用性和性能的同时,大大降低了部署门槛和维护负担(足够轻量话,对性能要求很小),非常适合希望在现有网络环境中快速、稳健地搭建旁路科学网关的场景(只要有可用的HTTP/SOCKS5代理~)。总的来说,两者各有适用场景,但如果目标是追求轻量、稳定、低运维成本,并且希望具备更好的环境普适性,那么本文的方案无疑更具优势。

需要说明的是,虽然本文介绍的方案最终呈现出轻量、稳定、低延迟的特性,但要实现这一结果,过程却并不简单。搭建过程中,不仅需要掌握 iptables、ebtables 的使用,还涉及 TCP/IP 网络基础、DNS 查询原理、HTTP/SOCKS5 协议转发机制、容器化技术(如 LXC 或虚拟机环境搭建与管理),以及 Linux 系统管理、包管理器使用、工具链编译与调试能力。同时,为了能够在遇到问题时快速定位,还需要具备一定的排错技巧,如抓包分析、日志排查和路由跟踪等。

某种意义上,相比直接采用集成度更高、配置向导更友好的科学软件 + TProxy/TUN 透明代理方案,本文的做法反而对底层知识和自主配置能力提出了更高要求。正是这种对细节的掌控,使得最终搭建出的旁路网关不仅轻量高效,更具备了良好的可控性和普适性。

因此,如果你希望通过本文的方法获得一个真正轻量、稳定、低维护成本的旁路网关体系,建议在动手之前,先对相关基础知识进行一定的了解:这不仅能让搭建过程更顺利,也有助于在未来维护和扩展时更加游刃有余。

分享这篇文章
博客内容均系原创,转载请注明出处!更多博客文章,可以移步至网站地图了解。博客的RSS地址为:https://blog.tangwudi.com/feed,欢迎订阅;如有需要,可以加入Telegram群一起讨论问题。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
       
error:
zh_CN