简介
SOCKS 是一个优秀的网络协议,主要被用来做代理,它的两个主要版本是 SOCKS4 和 SOCKS5,其中 SOCKS5 提供了对认证的支持。通常来说我们使用 SSH 工具可以构建简单的 SOCKS 协议通道,那么对于 netty 来说,是怎么提供对 SOCKS 的支持呢?一起来看看吧。
SocksMessage
首先是代表 SOCKS 消息对象的 SocksMessage。SocksMessage 是一个接口,它里面只有一个返回 SocksVersion 的 version 方法。
SocksVersion 表示的是 Socks 的版本号。在 netty 中,支持三个版本,分别是:
SOCKS4a((byte) 0x04),
SOCKS5((byte) 0x05),
UNKNOWN((byte) 0xff);
复制代码
其对应的数值是 SOCKS 协议中的 VER 字段,我们以 SOCKS4 协议为例,再复习一下 SOCKS 的协议结构:
既然 netty 中 SOCKS 有两个版本,相对于的 SocksMessage 接口就有两个实现,分别是 Socks4Message 和 Socks5Message。
Socks4Message
Socks4Messag 继承自 SocksMessage,表示的是 SOCKS4 的消息。
事实上,Socks4Messag 是一个 tag interface,它里面什么内容都没有。
public interface Socks4Message extends SocksMessage {
// Tag interface
}
复制代码
对于 SOCKS4 来说,有两种数据请求类型,分别是 CONNECT 和 BIND,这两种请求类型被定义在 Socks4CommandType 中:
public static final Socks4CommandType CONNECT = new Socks4CommandType(0x01, "CONNECT");
public static final Socks4CommandType BIND = new Socks4CommandType(0x02, "BIND");
复制代码
有请求就有响应,对应的有两个类,分别是 Socks4CommandRequest 和 Socks4CommandResponse。
对于 Request 来说,我们需要请求类型,USERID,DSTIP 和 DSTPORT 这几个数据:
Socks4CommandType type();
String userId();
String dstAddr();
int dstPort();
复制代码
对于响应来说,有四个不同的状态,分别是 SUCCESS、REJECTED_OR_FAILED、IDENTD_UNREACHABLE、IDENTD_AUTH_FAILURE。
public static final Socks4CommandStatus SUCCESS = new Socks4CommandStatus(0x5a, "SUCCESS");
public static final Socks4CommandStatus REJECTED_OR_FAILED = new Socks4CommandStatus(0x5b, "REJECTED_OR_FAILED");
public static final Socks4CommandStatus IDENTD_UNREACHABLE = new Socks4CommandStatus(0x5c, "IDENTD_UNREACHABLE");
public static final Socks4CommandStatus IDENTD_AUTH_FAILURE = new Socks4CommandStatus(0x5d, "IDENTD_AUTH_FAILURE");
复制代码
除了 Socks4CommandStatus 之外,响应请求还有 DSTIP 和 DSTPORT 两个属性。
Socks4CommandStatus status();
String dstAddr();
int dstPort();
复制代码
Socks5Message
同样的,对于 SOCKS5 来说,也有一个对应的接口 Socks5Message,这个接口也是一个 Tag interface,它里面什么都没有:
public interface Socks5Message extends SocksMessage {
// Tag interface
}
复制代码
对于 SOCKS5 来说,它的请求要比 SOKCS4 要复杂,首先的请求是一个初始化请求 Socks5InitialRequest,该请求包含了可以接受的认证列表。
这个列表用 Socks5AuthMethod 来表示,它包含 4 个方法:
public static final Socks5AuthMethod NO_AUTH = new Socks5AuthMethod(0x00, "NO_AUTH");
public static final Socks5AuthMethod GSSAPI = new Socks5AuthMethod(0x01, "GSSAPI");
public static final Socks5AuthMethod PASSWORD = new Socks5AuthMethod(0x02, "PASSWORD");
public static final Socks5AuthMethod UNACCEPTED = new Socks5AuthMethod(0xff, "UNACCEPTED");
复制代码
对于 Socks5InitialRequest 来说,它包含了一个 authMethods 的列表:
public interface Socks5InitialRequest extends Socks5Message {
List<Socks5AuthMethod> authMethods();
}
复制代码
对于 InitialRequest 来说,对应的也有 Socks5InitialResponse,它包含了服务端选择的 Socks5AuthMethod,所以对 Socks5InitialResponse 来说,它里面只包含了一个 Socks5AuthMethod:
public interface Socks5InitialResponse extends Socks5Message {
Socks5AuthMethod authMethod();
}
复制代码
客户端和服务器端协商好选择的认证协议之后,接下来就是认证的过程,如果使用的是用户名密码的模式,则对应的是 Socks5PasswordAuthRequest:
public interface Socks5PasswordAuthRequest extends Socks5Message {
String username();
String password();
}
复制代码
password 认证的结果只有两种结果,分别是 SUCCESS 和 FAILURE:
public static final Socks5PasswordAuthStatus SUCCESS = new Socks5PasswordAuthStatus(0x00, "SUCCESS");
public static final Socks5PasswordAuthStatus FAILURE = new Socks5PasswordAuthStatus(0xFF, "FAILURE");
复制代码
对于 Socks5PasswordAuthResponse 来说,它包含了一个认证的 status:Socks5PasswordAuthStatus。
认证完毕之后,接下来就可以发送 CommandRequest 了。对应的 Socks5CommandRequest 包含下面几个属性:
Socks5CommandType type();
Socks5AddressType dstAddrType();
String dstAddr();
int dstPort();
复制代码
对应的 Socks5CommandResponse 包含下面的属性:
Socks5CommandStatus status();
Socks5AddressType bndAddrType();
String bndAddr();
int bndPort();
复制代码
总结
以上就是 netty 对 SOCKS4 和 SOCKS5 协议的消息封装。基本上 netty 中的对象是和 SOCKS 协议一致的。
本文已收录于 http://www.flydean.com/36-netty-socks-support/
最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!
欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!
评论