天天看點

netty系列之:netty對SOCKS協定的支援

目錄

  • 簡介
  • SocksMessage
    • Socks4Message
    • Socks5Message
  • 總結

SOCKS是一個優秀的網絡協定,主要被用來做代理,它的兩個主要版本是SOCKS4和SOCKS5,其中SOCKS5提供了對認證的支援。通常來說我們使用SSH工具可以建構簡單的SOCKS協定通道,那麼對于netty來說,是怎麼提供對SOCKS的支援呢?一起來看看吧。

首先是代表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 2 4 可變

既然netty中SOCKS有兩個版本,相對于的SocksMessage接口就有兩個實作,分别是Socks4Message和Socks5Message。

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();
           

同樣的,對于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/

最通俗的解讀,最深刻的幹貨,最簡潔的教程,衆多你不知道的小技巧等你來發現!

歡迎關注我的公衆号:「程式那些事」,懂技術,更懂你!