文档章节

基于netty实现的socks5代理协议

xtuhcy
 xtuhcy
发布于 2016/12/28 17:28
字数 1734
阅读 641
收藏 2

基于netty实现的socks5代理协议

socks5协议

简介

socks5协议是一个标准的代理协议,工作在网络的四层,理论上可以代理任意应用层协议。协议标准RFC1928,用户/密码鉴权标准RFC1929。协议的中文版本可以参考这里

现有开源实现

用的比较多的是linux下的ss5开源实现,ss5的安装和配置如下:

./configure --with-debug --with-epollio --with-gssapi
make
make install
chomd +x /etc/init.d/ss5

修改/etc/init.d/ss5,增加端口,日志等配置:

export SS5_SOCKS_PORT=1081
export SS5_CONFIG_FILE=/tmp/ss5.conf
export SS5_PASSWORD_FILE=/tmp/ss5.passwd
export SS5_LOG_FILE=/tmp/ss5.log
export SS5_PROFILE_PATH=/tmp

修改/etc/sysconfig/ss5,配置服务器启动用户:

SS5_OPTS=" -u root"

修改/etc/opt/ss5/ss5.conf,配置鉴权方式:

permit -        0.0.0.0/0       -       0.0.0.0/0       -       -       -       -       -	
#不使用用户认证,
auth 0.0.0.0/0 – –
#使用用户名/密码认证,
auth 0.0.0.0/0 – u

修改/etc/opt/ss5/ss5.passwd,配置用户密码:

user passord

启动ss5服务:

service ss5 start

为什么要自己实现

需要更精确的记录代理访问日志,需要自己特殊的鉴权方式。ss5是基于c开发的,本人c语言一般,改起来还是稍显费劲,而基于java开发的socks5协议并没有特别成熟的,最终决定自己用netty4.1开发。

netty基本概念

NIO和BIO

BIO阻塞IO,NIO非阻塞IO。NIO基于事件通知机制,可以达到在单线程情况下同时处理多个IO。传统的BIO对每个IO请求都需要分配单独线程处理,而线程的分配是需要占用内存,分配的代价很高。因此传统的BIO每秒并发最多到千级别(和服务器配置相关),而NIO能支持每秒万级的并发。

NIO并不是没有缺点,NIO的异步特性对编程要求较高,和BIO的传统开发相比较,要更难控制,开发和调试难度也较大。

netty简介

在java开发中,提到NIO必会想到netty,netty是一个NIO开发框架,能降低NIO应用开发难度,开发者不需要关注通讯连接,可以将主要的精力放在对收到的信息进行编码,转换为对象,进行业务逻辑处理。netty框架是一个典型的管道过滤器模式的应用。netty3.x和4.x版本有较大的改动,本文主要使用netty4.1。

EventLoopGroup和EventLoop

前面提到NIO能在单线程模型相支持多IO,实际上线程并不是一个,而是有限的几个,这里的EventLoopGroup就是线程池,EventLoop就是线程。EventLoopGroup的线程数量和CPU核心数量相关,也可以初始化的时候自定义。

NIO应用的服务器端通常不止一个线程池,一般会建立一个boss线程池,一个worker线程池。boss线程池用来接收客户端连接,接收的连接交给worker线程池监听,一个worker线程可以监听多个io。

//boss线程池,这里定义线程数量为2
EventLoopGroup boss = new NioEventLoopGroup(2);
//worker线程池,线程数量结合cpu核心计算出来Runtime.getRuntime().availableProcessors() * 2
EventLoopGroup worker = new NioEventLoopGroup();

ServerBootstrap和Bootstrap

Bootstrap是一个builder模式的类型构造器,ServerBootstrap用于服务器端的构造,Bootstrap用于客户端的构造。主要配置线程池、ChannelFactory、基本参数、ChannelHandler链表初始化等。ServerBootstrap调用bind监听端口,Bootstrap调用connect连接服务器端。

在netty中ChannelFuture会经常碰到,由于netty所有的操作都是异步的,bind,connet,close等都不会立即返回接口,都是通过监听方法回调。通过调用ChannelFuture.addListener()添加监听方法。ChannelFutureListener里有几个内置的监听方法CLOSE,CLOSE_ON_FAILURE,FIRE_EXCEPTION_ON_FAILURE。

Channel,ChannelPipeline,ChannelHandler,ChannelHandlerContext

一个Channel分配一个ChannelPipeline,每个ChannelPipeline里是多个ChannelHandler组成的链表,每个ChannelHandler会对应一个ChannelHandlerContext。看看下面的图就能明白: 输入图片说明

  • Channel负责底层通讯,Channel会绑定到一个worker线程中,Channel在收到Event后会传递给ChannelPipeline,Event会在ChannelHandler链表中流转。 输入图片说明

  • ChannelPipeline负责消息的传递,里面是一个ChannelHandler的组成的双向链表,按消息类型分为上行消息ChannelHandler和下行消息ChannelHandler。因此就有了两个子接口,ChannelInboundHandler只关心上行消息,ChannelOutboundHandler只关心下行消息。如果上下行消息都需要关系可以继承ChannelDuplexHandler。ChannelHandler通过调用fireChannelRead()将上行消息传递给下一个Handler,通过调用write()形成下行消息,调用write()后,上行消息将不再传递给下一个Handler。

  • ChannelHandler是处理消息的单元,是netty开发的核心。开发人员大部分都是在写各种Handler。netty内置了很多协议的handler,但是比较遗憾文档不多。上面已经说过,ChannelHandler按消息类型分可以分为ChannelInboundHandler和ChannelOutboundHandler。按功能分为编解码Handler(编码Encoder/解码Decoder)和消息处理Handler。通常需要将上行消息需要进行解码转换为对象,再将对象传递给之后的业务处理Handler。业务处理完毕,将下行对象编码后转换为ByteBuf交给Channel传递给网络层。

ByteBuf

理解ByteBuf对消息的编解码有很多好处,ByteBuf是Channel进行网络通信的核心对象,ByteBuf就像一个缓冲池一样,ByteBuf逻辑上就是一个byte容器。ByteBuf里的数据被两个指针划分为三个部分,如下图所示: 输入图片说明

  • reader index前面的数据是已经读过的数据,这些数据可以扔掉
  • 从reader index开始,到writer index之前的数据是可读数据
  • 从writer index开始,为可写区域

使用netty实现socks5协议

netty中已经内置了socks5协议的编解码,我们只需要实现逻辑处理Handler就行,下面是几个主要的编解码codec:

  • Socks5InitialRequestDecoder负责服务器和客户端协商鉴权方式,返回服务器端支持的鉴权方式,会将消息解码为DefaultSocks5InitialRequest对象
  • Socks5PasswordAuthRequestDecoder是使用用户名和密码的鉴权方式的协议,返回鉴权是否通过,会将消息解码为DefaultSocks5PasswordAuthRequest对象
  • Socks5CommandRequestDecoder负责目标服务器的连接建立,返回建立是否成功,会将消息解码为DefaultSocks5CommandRequest对象
  • Socks5ServerEncoder负责所有下行对象的编码,转换为ByteBuf

编解码工作不需要我们自己开发,剩下的事情就比较简单,只需要处理各个层级的Socks5Request就行了。ChannelHandler链的结构如下:

Socks5ServerEncoder
Socks5InitialRequestDecoder
Socks5InitialRequestHandler(实现自己的处理逻辑)
Socks5PasswordAuthRequestDecoder
Socks5PasswordAuthRequestHandler(实现自己的处理逻辑)
Socks5CommandRequestDecoder
Socks5CommandRequestHandler(实现自己的处理逻辑)

通过实现3个ChannelHandler,我们就能轻松搞定一个socks5协议。全部代码可以在github上查到,项目名为socks5-netty

© 著作权归作者所有

共有 人打赏支持
xtuhcy

xtuhcy

粉丝 105
博文 17
码字总数 20302
作品 1
北京
后端工程师
私信 提问
Netty实现shadowsocks客户端

Shadowsocks是什么 shadowsocks是基于socks5协议实现的代理方式,分为服务器和客户端,双端之间通过使用指定的加密方式(AES,BlowFish,Table等)进行数据传输,有效的突破了GFW。 整个流程可以...

ksfzhaohui
2016/09/08
2.1K
6
Proxy-Go v6.0 强势发布:企业版开源 , 大量新特性

Proxy-Go v6.0 企业版开源啦。Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5代理服务器,支持正向代理、反向代理、透明代理、内网穿透、TCP/UDP端口映射、SSH中转、TLS加密传...

狂奔的蜗牛.
09/06
4K
11
HttpClient4基于Shadowsocks-netty的Socks代理

前言 最近想批量下载一些国外网站的视频,之前写过一个代理程序shadowsocks-netty,打算直接 用它来当作客户端代理程序,而HttpClient4也支持Socks代理;所有准备用HttpClient4来访问国外网站...

ksfzhaohui
2017/10/18
0
0
Proxy-Go v5.2 发布,重构 SOCKS5/SPS 的 UDP 功能

Proxy-Go v5.2发布了。Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5代理服务器,支持正向代理、反向代理、透明代理、内网穿透、TCP/UDP端口映射、SSH中转、TLS加密传输、协...

狂奔的蜗牛.
07/09
1K
6
Proxy-Go v4.0 发布,内网穿透使用多路复用重构

Proxy-Go v4.0 发布了。Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5代理服务器,支持正向代理、内网穿透、TCP/UDP端口转发、SSH中转。 更新内容: 内网穿透三端重构了一个...

狂奔的蜗牛.
2017/12/04
2.8K
25

没有更多内容

加载失败,请刷新页面

加载更多

追加字节能优化性能

这种方式看起来很神奇,单如果深入理解处理器架构就能理解其中的奥秘。让我们先来看看LinkedTransferQueue这个类,它使用一个内部类型来定义队列的头队列Head和尾节点tail,二这个内部类Pad...

无知的小狼
21分钟前
0
0
性能优化(JVM概念及配置)

虚拟机组成 一次编写,到处运行 Java虚拟机是对操作系统的模拟,隔离差异 2018编程语言排行榜 一个复杂的构架 虚拟机的内部概念 运行原理 编译器,解释器执行流程 内存分配-线程模型 栈帧模型...

这很耳东先生
28分钟前
3
0
Scala之初步认识与环境准备

1. 了解 Scala 1.1. 什么是 Scala Scala 是 Scalable Language 的简写,是一门多范式的编程语言。 Scala设计的初衷是要集成面向对象编程和函数式编程的各种特性。Scala运行于Java平台(Java虚...

飞鱼说编程
49分钟前
4
0
Vue项目分环境打包的实现步骤

在项目开发中,我们的项目一般分为开发版、测试版、Pre版、Prod版。Vue-cli的默认环境一只有dev和prod两个,之前每次要发布测试版或Pre版都是修改了源码中API地址后打包,这样很麻烦。如果能...

peakedness丶
49分钟前
6
0
vue+lowdb+express

搭建流程: 1.安装Node.js; 2.安装npm; 3.安装Express; 搭建流程 npm install -g express 安装 express 生成器 npm install -g express-generator 查看是否安装成功,随便输的一个命令...

Js_Mei
54分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部