shadowsocks-libev udp转发原理简介

  1. ss_local作为一个sock5服务器,接收来自socks5客户端的数据包。在ss_local启动后,即创建一个udp socket,并bind到一个端口。该udp socket用于接收所有来自socks5客户端的udp包。
  2. 根据socks5规范,socks5客户端和ss_local建立一个tcp连接进行握手,握手成功后ss_local返回上面创建的udp socket的端口给socks5客户端
  3. socks5客户端将udp包包装成socks5的格式(即原始数据前加上socks5 request header)发送给ss_local

    SOCKS5 UDP包格式

    +—-+——+——+———-+———-+———-+

    |RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA |

    +—-+——+——+———-+———-+———-+

    | 2 | 1 | 1 | Variable | 2 | Variable |

    +—-+——+——+———-+———-+———-+

  4. 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字节域名长度+域名文本。

  5. ss_server将包解密后,去除addr header后将DATA发送到addr header指定的目标地址。如果addr是个域名还要先进行DNS解析。ss_server会维护一个包含fd和addr等内容的cache,避免对于重复的域名重复解析。

  6. ss_server接收来自目的地址的返回的udp包,将他加上addr header并加密发送给ss_local
  7. ss_local解密来自ss_server的包,前面添加3字节0,构建成socks5 udp包后发送回客户端

整体流程和几个重要的函数

  1. init_udprelay : 创建udp server socket, 创建server_ctx_t,启动libev io

    读事件监听,准备接收来自客户端的udp包
  2. server_recv_cb: 当ss-local可接收来自客户端的udp数据包时调用,这个函数里面会读取数据包并处理成shadowsocks udp包的格式并加密后发送到ss-server。
  3. server_recv_cb:当ss-server可接收来自ss-local的加密udp数据包时调用。(同一个函数,不过部分内容通过宏区分了)这个函数里面会读取并解密数据包,解析出addr header,将数据部分发送到addr header里面的地址。如果addr是域名则先做域名解析。
  4. remote_recv_cb:当ss-server可接收来自目的服务器的udp包时调用。这个函数里面读取数据包加上addr header后加密然后发送给ss-local
  5. remote_recv_cb: 当ss-local可接收来自ss-server的加密udp数据包时调用。ss-local会读取数据包并解密,验证addr header,并在数据包最前面加上三个字节的0以构成合法的socks5 udp包,然后将之发送回socks5客户端。

ss-libev 源码解析udp篇 (1)的更多相关文章

  1. ss-libev 源码解析udp篇 (4)

    本篇分析remote_recv_cb,这是整个udp转发的反方向,即读取从后端发送过来的数据再发送给前端.对于ss-server,读取到的数据是目标地址的udp服务器发送回来的响应数据,ss-serv ...

  2. ss-libev 源码解析udp篇 (3)

    本篇分析server_recv_cb,这个是udp转发中最重要的函数. server_recv_cb: 当ss-local或ss-server接收到来自前端的udp数据包时调用.这个函数代码比较多,除 ...

  3. ss-libev 源码解析udp篇 (2)

    UDP relay的代码基本都在udprelay.c中,无论ss-local还是ss-server的代码都在一起,使用宏MODULE_LOCAL,MODULE_REMOTE等区分开.代码虽然不是很多, ...

  4. jQuery2.x源码解析(缓存篇)

    jQuery2.x源码解析(构建篇) jQuery2.x源码解析(设计篇) jQuery2.x源码解析(回调篇) jQuery2.x源码解析(缓存篇) 缓存是jQuery中的又一核心设计,jQuery ...

  5. jQuery2.x源码解析(构建篇)

    jQuery2.x源码解析(构建篇) jQuery2.x源码解析(设计篇) jQuery2.x源码解析(回调篇) jQuery2.x源码解析(缓存篇) 笔者阅读了园友艾伦 Aaron的系列博客< ...

  6. jQuery2.x源码解析(设计篇)

    jQuery2.x源码解析(构建篇) jQuery2.x源码解析(设计篇) jQuery2.x源码解析(回调篇) jQuery2.x源码解析(缓存篇) 这一篇笔者主要以设计的角度探索jQuery的源代 ...

  7. jQuery2.x源码解析(回调篇)

    jQuery2.x源码解析(构建篇) jQuery2.x源码解析(设计篇) jQuery2.x源码解析(回调篇) jQuery2.x源码解析(缓存篇) 通过艾伦的博客,我们能看出,jQuery的pro ...

  8. Shiro源码解析-Session篇

    上一篇Shiro源码解析-登录篇中提到了在登录验证成功后有对session的处理,但未详细分析,本文对此部分源码详细分析下. 1. 分析切入点:DefaultSecurityManger的login方 ...

  9. myBatis源码解析-类型转换篇(5)

    前言 开始分析Type包前,说明下使用场景.数据构建语句使用PreparedStatement,需要输入的是jdbc类型,但我们一般写的是java类型.同理,数据库结果集返回的是jdbc类型,而我们需 ...

随机推荐

  1. spring定时器(注解的形式)

    最近有个需求,要在凌晨的时候,根据某几张表生成一张定时任务表里的数据,数据的状态为0(未整改),然后在当天晚上,再把这些数据的状态没改变的,改变状态为1(待整改),然后要用到定时器,百度了一下用注解形 ...

  2. Docker 学习记录

    docker logs 查看日志 docker logs  容器id docker logs -f 容器id 这次命令后面添加了一个新的标识 -f. 和 tail -f 类似, docker logs ...

  3. spring boot 使用拦截器,注解 实现 权限过滤

    http://www.cnblogs.com/zhangXingSheng/p/7744997.html spring boot 使用拦截器 实现 用户登录拦截 http://www.cnblogs. ...

  4. 实例化后的list的默认值

    public class List默认值 { public static void main(String[] args) { List<String> arrayList = new A ...

  5. 真正在线编辑的在线web编辑器

    最近正在研究开发一款在线web编辑器架构,这是一款真正傻瓜式的web编辑器,可以在正常浏览页面的情况进行编辑,经过测试,对于一般网页页面来说非常好用方便,操作更简单. 一般的在线web编辑器虽说提供了 ...

  6. Svn Replacement For Git Stash

    svn 实现git stash类似的功能 % svn diff > WorkInProgress.txt % svn revert -R . <make changes> % svn ...

  7. 学习 nginx (持续更新)

    什么是代理与反向代理,有什么应用场景? 平常经常听别人说代理与反向代理,那么这二者到底有什么区别呢? 代理 场景:我需要访问一个服务器C,但是由于某些原因我无法访问到它,(典型的就是你FQ,然后fai ...

  8. Qt5.3中qml ApplicationWindow设置窗口无边框问题

    这个版本的qt在这里有点bug.. 设置ApplicationWindow的flags属性为Qt.FramelessWindowHint的确可以使程序无边框,但是同时程序在任务栏的图标也没了. 看文档 ...

  9. RMAN中format的参数

    (转自:http://blog.chinaunix.net/uid-23079711-id-2554290.html) format 的替换变量,注意大小写! 1.     %d --数据库的db_n ...

  10. 【zzuli-1923】表达式求值

    题目描述 假设表达式定义为:1. 一个十进制的正整数 X 是一个表达式.2. 如果 X 和 Y 是 表达式,则 X+Y, X*Y 也是表达式; *优先级高于+.3. 如果 X 和 Y 是 表达式,则 ...