1.为什么使用TPROXY才能代理UDP

在进行TCP的代理时,只要在NET表上无脑进行REDIRECT就好了。例如使用ss-redir,你只要把tcp的流量redirect到ss-redir监听的端口上就OK了。但是当你使用这种方法的时候,就会不正常,因为对于UDP进行redirect之后,原始的目的地址和端口就找不到了。

这是为什么呢?

ss-redir的原理很简单:使用iptables对PREROUTING与OUTPUT的TCP/UDP流量进行REDIRECT(REDIRECT是DNAT的特例),ss—redir在捕获网络流量后,通过一些技术手段获取REDIRECT之前的目的地址(dst)与端口(port),连同网络流量一起转发至远程服务器。

针对TCP连接,的确是因为Linux Kernel连接跟踪机制的实现才使获取数据包原本的dst和port成为可能,但这种连接跟踪机制并非只存在于TCP连接中,UDP连接同样存在,conntrack -p udp便能看到UDP的连接跟踪记录。内核中有关TCP与UDP的NAT源码/net/netfilter/nf_nat_proto_tcp.c和/net/netfilter/nf_nat_proto_udp.c几乎一模一样,都是根据NAT的类型做SNAT或DNAT。

那这究竟是怎么一回事?为什么对于UDP连接就失效了呢?

回过头来看看ss-redir有关获取TCP原本的dst和port的源码,核心函数是getdestaddr:

static int

getdestaddr(int fd, struct sockaddr_storage *destaddr)

{

socklen_t socklen = sizeof(*destaddr);

int error = 0;

error = getsockopt(fd, SOL_IPV6, IP6T_SO_ORIGINAL_DST, destaddr, &socklen);

if (error) { // Didn't find a proper way to detect IP version.

error = getsockopt(fd, SOL_IP, SO_ORIGINAL_DST, destaddr, &socklen);

if (error) {

return -1;

}

}

return 0;

}

在内核源码中搜了下有关SO_ORIGINAL_DST的东西,看到了getorigdst:

static int

getorigdst(struct sock *sk, int optval, void __user *user, int *len)

{

const struct inet_sock *inet = inet_sk(sk);

const struct nf_conntrack_tuple_hash *h;

struct nf_conntrack_tuple tuple;

memset(&tuple, 0, sizeof(tuple));

lock_sock(sk);

tuple.src.u3.ip = inet->inet_rcv_saddr;

tuple.src.u.tcp.port = inet->inet_sport;

tuple.dst.u3.ip = inet->inet_daddr;

tuple.dst.u.tcp.port = inet->inet_dport;

tuple.src.l3num = PF_INET;

tuple.dst.protonum = sk->sk_protocol;

release_sock(sk);

/* We only do TCP and SCTP at the moment: is there a better way? */

if (tuple.dst.protonum != IPPROTO_TCP &&

tuple.dst.protonum != IPPROTO_SCTP) {

pr_debug("SO_ORIGINAL_DST: Not a TCP/SCTP socket\n");

return -ENOPROTOOPT;

}

We only do TCP and SCTP at the moment。Oh,shit!只针对TCP与SCTP才能这么做,并非技术上不可行,只是人为地阻止罢了。

2.TPROXY

为了在redirect UDP后还能够获取原本的dst和port,ss-redir采用了TPROXY。Linux系统有关TPROXY的设置是以下三条命令:

ip rule add fwmark 0x2333/0x2333 pref 100 table 100

ip route add local default dev lo table 100

iptables -t mangle -A PREROUTING -p udp -j TPROXY --tproxy-mark 0x2333/0x2333 --on-ip 127.0.0.1 --on-port 1080

大意就是在mangle表的PREROUTING中为每个UDP数据包打上0x2333/0x2333标志,之后在路由选择中将具有0x2333/0x2333标志的数据包投递到本地环回设备上的1080端口;对监听0.0.0.0地址的1080端口的socket启用IP_TRANSPARENT标志,使IPv4路由能够将非本机的数据报投递到传输层,传递给监听1080端口的ss-redir。IP_RECVORIGDSTADDR与IPV6_RECVORIGDSTADDR则表示获取送达数据包的dst与port。

可问题来了:要知道mangle表并不会修改数据包,那么TPROXY是如何做到在不修改数据包的前提下将非本机dst的数据包投递到换回设备上的1080端口呢?

这个问题在内核中时如何实现的,还待研究,但是确定是TPROXY做了某些工作。

TPROXY主要功能:

重定向一部分经过路由选择的流量到本地路由进程(类似NAT中的REDIRECT)

在非本地IP上起监听。监听后就可以转发了(神奇吧)

TPROXY要解决的两个重要的问题

1.套接字如何监听到非本地IP地址。

先用setsockopt函数为套接字设置IP_TRANSPARENT标识,再去监听0.0.0.0地址这样的方式来实现监听任意IP。

2.如何获取的原始目标的端口 。

先调用setsockopt (s, IPPROTO_IP, IP_RECVORIGDSTADDR, &n, sizeof(int))函数为套接字设置IP_RECVORIGDSTADDR标识,然后通过recvmsg函数从tproxy那边接受发过来的msghdr结构体信息,并循环遍历cmsghdr成员最终获取到原始目标的地址和端口,也就是说tproxy会向msghdr(附属数据结构)填入原始目标ip和端口信息,再通过sendmsg函数发送给代理应用。

tproxy_Linux使用TPROXY进行UDP的透明代理相关推荐

  1. iptables:tproxy做透明代理

    什么是透明代理 客户端向真实服务器发起连接,代理机冒充服务器与客户端建立连接,并以客户端ip与真实服务器建立连接进行代理转发.因此对于客户端与服务器来说,代理机都是透明的. 如何建立透明代理 本地so ...

  2. 什么是 tproxy 透明代理?

    在 Istio 最新的 Ambient 模式中,使用了 tproxy 做透明流量劫持(见此博客 [1] ),这与 Sidecar 模式中基于 IPtables 的流量劫持方式有些许不同,这篇文文章,我 ...

  3. # 什么是Tproxy透明代理

    什么是Tproxy透明代理 文章目录 什么是Tproxy透明代理 1 什么是代理? 1.1 代理的功能 1.2 代理的分类 2 使用 tproxy 透明代理 3 透明代理的优点 4 透明代理的缺点 5 ...

  4. 记玄妙莫测的透明代理

    本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可. 本作品 (李兆龙 博文, 由 李兆龙 创作),由 李兆龙 确认,转载请注明版权. 若无特殊说明,内核源码版本为4.1 ...

  5. tpproxy-tcp透明代理

    tcp transparent proxy Background  最近有个需求,需要在路由器设备中截获数据包,从而实现中转.按照下面的拓补,说明.我们需要在主机h2上截获h1发往h3的TCP协议包. ...

  6. redsocks 透明代理

    整体架构 #mermaid-svg-ON8oZJjAaCC8MQPU .label{font-family:'trebuchet ms', verdana, arial;font-family:var ...

  7. 透明代理解决方案(一)

    透明代理解决方案(一) 最近做基于 Iptables REDIRECT 的透明代理方案时遇到一个问题,解决的过程中涉及到几个重要的网络相关知识点,记录在这里以便查找. 方案说明 网上有很多种透明代理的 ...

  8. 使用squid配置透明代理并对上网行为进行控制

    使用Squid配置透明代理 环境:CentOS 6.4 + squid-3.1.10-20.el6_5.3.x86_641.检查squid是否默认安装,没有安装先安装 rpm -qa squid 假如 ...

  9. Haproxy全透明代理

    1. 系统环境搭建 操作系统Centos7 内核版本3.10 Centos7已自带TPROXY模块,不需要安装TPROXY 2. Haproxy下载,编译,安装,配置 下载地址 http://www. ...

最新文章

  1. 2021年加拿大工程院院士名单出炉,杨强、张大鹏、刘学等多位华人入选
  2. Java语言实现简单FTP软件------源码放送(十三)
  3. 第一篇|腾讯开源项目盘点:WeUI,WePY,Tinker,Mars等
  4. 数字图像处理:视觉系统中的坐标系介绍
  5. Qt工作笔记-Qt文档阅读笔记-qualifiedName()的官方解析及XML使用名称空间
  6. libevent源码深度剖析五
  7. 从2000年到2019年
  8. 10个最棒的jQuery视频插件
  9. linux文件目录类命令--pwd命令
  10. Spring MVC请求-响应流
  11. 关于.NET异常 你应该知道的更多点
  12. 解读《美国国家BIM标准》 – BIM能力成熟度模型(十二)
  13. 线性混合模型及R实现
  14. 怎么把计算机加入网络打印机共享打印机共享,打印机共享怎么设置
  15. 怎么改自己手机的ip地址
  16. 16春季计算机应用基础,16春季福师《计算机应用基础》在线作业一.doc
  17. 推荐几个短网址赚钱站
  18. python自动化模拟浏览器
  19. 字节-测试开发-面试
  20. 如何使用 Podman 签署和分发容器镜像

热门文章

  1. bash脚本编程之一 条件判断及算术运算
  2. Java NIO示例:多人网络聊天室
  3. PHP计算表达式-栈
  4. 一个简单的三层架构例子(.NET入门)
  5. 信息网络安全技术知识
  6. Tensorflow实现简单神经网络
  7. 看看如何解决“SQL Server只能使用Windows身份登录,不能使用sa等Sql server身份进行登录”的问题...
  8. MVC 服务器文件下载
  9. dwz中弹出的窗口页面如何获取前页面(点击按钮的页面)的元素???
  10. 20200817-Mysql 底层数据结构及Explain详解