簡介
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的協議結構:
含義 | VER | CMD | DSTPORT | DSTIP | ID |
---|---|---|---|---|---|
位元組個數 | 1 | 1 | 2 | 4 | 可變 |
既然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/
最通俗的解讀,最深刻的乾貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!
歡迎關注我的公眾號:「程式那些事」,懂技術,更懂你!