使用 Pipy 和 eBPF 实现透明代理

背景

透明代理

透明代理是一种网络中间件,它能够在用户不知情的情况下拦截和转发网络流量。与传统代理不同,透明代理不需要在用户端配置特定的代理设置,而是通过在网络层面拦截流量来实现代理功能。透明代理通常被用于网络管理、安全策略实施、流量监控和优化等方面。它可以用于实现诸如内容过滤、缓存加速、流量控制、负载均衡等功能。常见的 TPROXY、NAT、Divert 等技术都可以用来实现透明代理。

eBPF

eBPF 是一种高效、灵活的内核技术,允许用户空间程序安全地执行预编译和限制在 Linux 内核空间中运行的程序(即 eBPF 程序),而不需要更改内核源代码或加载内核模块。近几年 eBPF 在网络方面的广泛应用,使其成为实现透明代理的可选技术之一。

Pipy 从 0.99.1 之后加入了对 BPF 的支持,可以加载和解析 BPF 程序;1.0 的语法升级,让其在实现控制逻辑方面更加得心应手。今天我们就来介绍如何使用 Pipy + eBPF 实现一个简单的透明代理。

注:文中所有的代码都可以在 Pipy 仓库中找到:https://github.com/flomesh-io/pipy/tree/main/samples/bpf/transparent-proxy。

快速开始

克隆代码。

git clone https://github.com/flomesh-io/pipy.git
cd samples/bpf/transparent-proxy

编译 BPF 程序,之后可以在目录中找到编译好的 .o 文件。

make

启动透明代理。

sudo pipy main.js

成功运行后,代理会监听端口 18000。接着我们发送请求测试一下:

curl -L bing.com

在代理的控制台,我们可以找到请求和相应的日志。

GET / bing.com
  301 Moved Permanently
GET / www.bing.com
  200 OK

在整个过程中,代理对客户端保持透明,无需进行任何代理配置。

接下来,我们将深入探讨透明代理的实现方式。

实现

eBPF 程序设计

在实现中用到了三个 eBPF 程序,每个程序负责不同的网络拦截与转发任务:

  • 连接建立时的地址替换第一个 eBPF 程序 cg_connect4 附加到 connect 系统调用上。当客户端尝试与目标服务器建立连接时,这个程序将目标的 IP 地址和端口替换为 Pipy 代理的地址(通常是本地地址 127.0.0.1)和端口。同时,它将原始的目标地址和端口保存到 struct sock 中,并将 socket 的 cookie 与该 sock 结构的映射关系保存在 map_socks 中,用于之后的查询和数据转发。
  • 连接成功后的源地址记录第二个 eBPF 程序 cg_sock_ops 在连接成功建立后执行,负责记录源地址和端口,并将这些信息更新到 map_socks 里对应的 sock 中。此外,它还将源端口和 socket 的 cookie 的映射关系保存在 map_ports 中,为后续数据转发提供必要的信息。
  • 基于原始目的地信息的连接与转发第三个 eBPF 程序 cg_sock_opt 触发于 Pipy 通过 getsockopt 查询原始
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值