ss-libev 源码解析udp篇 (1)
来源:互联网 发布:做淘宝怎么发快递 编辑:程序博客网 时间:2024/06/05 19:43
shadowsocks-libev udp转发原理简介
- ss_local作为一个sock5服务器,接收来自socks5客户端的数据包。在ss_local启动后,即创建一个udp socket,并bind到一个端口。该udp socket用于接收所有来自socks5客户端的udp包。
- 根据socks5规范,socks5客户端和ss_local建立一个tcp连接进行握手,握手成功后ss_local返回上面创建的udp socket的端口给socks5客户端
- socks5客户端将udp包包装成socks5的格式(即原始数据前加上socks5 request header)发送给ss_local
SOCKS5 UDP包格式
+—-+——+——+———-+———-+———-+
|RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA |
+—-+——+——+———-+———-+———-+
| 2 | 1 | 1 | Variable | 2 | Variable |
+—-+——+——+———-+———-+———-+ ss_local 从Socks5 UDP包中取出ATYP开始的内容(即ATYP开始的addr header加上DATA),加密后发送到ss_server。根据加密方式不同,加密包的格式也不同,主要分为stream加密和AEAD加密两大类。(注:目前版本已经去掉OTA)
UDP (before encryption)
+——+———-+———-+———-+
| ATYP | DST.ADDR | DST.PORT | DATA |
+——+———-+———-+———-+
| 1 | Variable | 2 | Variable |
+——+———-+———-+———-+
.
ATYP可能的取值是1(ipv4地址),3(域名),4(ipv6地址)。
如果ATYP是3,则DST.ADDR是1字节域名长度+域名文本。ss_server将包解密后,去除addr header后将DATA发送到addr header指定的目标地址。如果addr是个域名还要先进行DNS解析。ss_server会维护一个包含fd和addr等内容的cache,避免对于重复的域名重复解析。
- ss_server接收来自目的地址的返回的udp包,将他加上addr header并加密发送给ss_local
- ss_local解密来自ss_server的包,前面添加3字节0,构建成socks5 udp包后发送回客户端
整体流程和几个重要的函数
- init_udprelay : 创建udp server socket, 创建server_ctx_t,启动libev io
读事件监听,准备接收来自客户端的udp包 - server_recv_cb: 当ss-local可接收来自客户端的udp数据包时调用,这个函数里面会读取数据包并处理成shadowsocks udp包的格式并加密后发送到ss-server。
- server_recv_cb:当ss-server可接收来自ss-local的加密udp数据包时调用。(同一个函数,不过部分内容通过宏区分了)这个函数里面会读取并解密数据包,解析出addr header,将数据部分发送到addr header里面的地址。如果addr是域名则先做域名解析。
- remote_recv_cb:当ss-server可接收来自目的服务器的udp包时调用。这个函数里面读取数据包加上addr header后加密然后发送给ss-local
- remote_recv_cb: 当ss-local可接收来自ss-server的加密udp数据包时调用。ss-local会读取数据包并解密,验证addr header,并在数据包最前面加上三个字节的0以构成合法的socks5 udp包,然后将之发送回socks5客户端。
- ss-libev 源码解析udp篇 (1)
- ss-libev 源码解析udp篇 (2)
- ss-libev 源码解析udp篇 (3)
- ss-libev 源码解析udp篇 (4)
- ss-libev 源码解析local篇(4): server_recv_cb之STAGE_STREAM
- ss-libev 源码解析local篇(1): ss_local的启动,客户端连入
- ss-libev 源码解析local篇(5):ss-local之remote_send_cb
- ss-libev 源码解析local篇(2):ss_local和socks5客户端握手
- ss-libev 源码解析local篇(3): server_recv_cb之SNI和STAGE_PARSE
- Libev源码解析
- libev源码分析1
- vultr+ss-libev+hiwifi
- libev源码解析——总览
- libev源码解析——调度策略
- libev源码解析——定时器原理
- libev源码解析——I/O模型
- libev源码解析——定时器监视器和组织形式
- libev 源码浅析
- [mark]:eclipse快捷键和使用技巧
- Redis常用命令
- jq实现循环遍历树形结构的CheckBox根据父级选中子级
- sql 更新标识列的当前最大id
- Ubuntu下安装并配置TexStudio
- ss-libev 源码解析udp篇 (1)
- 判断玩家是否开全图挂
- String、StringBuffer与StringBuilder之间区别
- 通过轮廓简单实现一个圆图
- FFMPEG类库打开流媒体的方法(需要传参数的时候)
- java 设计模式-单例模式
- linux--chown
- docker 安装showdoc
- jQuery——选中、不选中、全选、取消全选等复选框操作