[復刻版] SOCKS5のプロトコルの概要

SOCKS5のプロトコルの紹介

SOCKS5は何ですか

おそらく、あなたはSOCKS5のを聞いていますが、ShadowSocksを聞いたことがある必要があり、SOCKS5プロトコルは、内部ShadowSockSの使用です。

靴下「ソケット」の頭文字であるので、SOCKS5もsockets5呼ばれます。

RFC住所:

靴下は、送信され、クライアントと外部ネットワークの中間的通信サーバとの間で使用されるネットワーク伝送プロトコルです。OSIモデルに従って分割、セッション層、トランスポート層に属すると層との間に配置SOCKSプロトコルを表します。

ファイアウォールクライアントは外部サーバー、ちょうどSOCKSプロキシサーバーなどの接続にアクセスするとき。契約は、高度な権限を持つユーザーが外部リソースにアクセスできるように許可されたユーザは、ファイアウォールの制限を通過できるようにするために設計の始まりです。時間の10年後、ネットワークアプリケーションの多くはSOCKS5プロキシをサポートしています。

プロトコルは元々、バージョン4にそれを拡張NEC英ダ・リーのことで、その後、デビッドKoblasによって開発され、契約の最新バージョンは、以前のバージョンと比較して、5であるた、SOCKS5は、以下の機能拡張が行わ:

  • UDPプロトコルのサポートが追加されました。
  • これは、複数のユーザ認証方法及び通信の暗号化をサポートしています。
  • それは、よりエレガントに、ドメインの名前解決方法のための靴下サーバーを変更します。

SOCKS5の使用シナリオ

設計された靴下プロトコルは、ネットワークの分離の場合には、いくつかのスタッフのネットワークアクセスを向上させるようにすることですが、国は、ほとんどの機関、そのような使用を整理しているようです。通常の状況下で、我々は、同じ目的を達成するために更新されたネットワークセキュリティ技術を使用します。

プロトコルとは逆に設計された画期的なネットワーク・トラフィックの制限、:しかし、socksCap32やPSDなどのソフトウェアに起因する、人々は、プロトコルを新たな用途を靴下見つけます。

ここでは2つの典型的なアプリケーションのシナリオは以下のとおりです。

  • オンラインゲームのサーバーは米国のみの国家IP接続を可能にします。米国以外のプレイヤーは、この制限を打破するためには、あなたはその後、SOCKS5プロキシサーバーの面積を見つけることができるPSDオンラインクライアントを引き継いだ、SOCKS5プロキシサーバーを介してゲームサーバーに接続します。ゲームサーバは、プレイヤークライアントがゲームにプレイヤーをできるように、地域に位置していると思われるように(また、天**の科学と呼ばれ、フォワードプロキシです)。

image.png

  • ファイアウォールは、プロトコルがSOCKS5ポート80を利用することができ、公共のインターネットサーバに接続されたオープンリスニングSOCKS5サーバが他のポートに接続することができ、通信のサーバポート(例えば、HTTPポート80)の一部のみを可能にします。(私たちはしばしば言う次いで、周囲のhttpでインターネットを使用してプロキシネットワークがHTTPを介して靴下と呼ばれるネットワークサービスの無制限利用することができ、いくつかの追加の技術的手段は、HTTPプロキシサーバのも、内部をだますことができます使用します)壁を通して。

  • ネットワークの浸透:大学では、学校は私たちのサーバリソースの多くを与え、我々はイントラネットを使用することができます。しかし、家に帰る冬休みの後、学校のネットワークに入ることができない、あなたは、ネットワーク内のサーバー・リソースに接続することはできません。ソリューション:パブリックネットワークVPSのSOCKSプロキシ、内部ネットワークとWebサーバと靴下のVPSポートに乗るには、を介して取得するには、NATこのWebサーバーを介してすべてのイントラネットサーバリソース(共通ピーナッツの殻にアクセスすることができます浸透および同様)。image.png

もちろん、プロキシサーバの使用は、通信遅延は避けられない表示され、それは、サーバが近くに位置していた(オペレーターを介して)同じネットワークを選択するようにしてください。

HTTPプロキシとの比較

靴下は、複数のユーザ認証方法及び通信の暗号化をサポートしています。

ネットワーク層よりも低いHTTPプロキシ作業靴下:靴下クライアントが靴下を接続しようとするため、そのエージェント・ソフトウェアに通知するためにハンドシェイクプロトコルを使用して、可能な限り透明で動作し、従来の薬剤は解釈されてもよいし、ヘッダを書き換える(例えば、 FTPなどの別の基本的なプロトコルを使用しているが、唯一のHTTPプロキシが必要なHTTPサーバにHTTPリクエストを転送します)。

UDPパケットの転送をサポートしていないHTTPプロトコルをTCPに属する一方で、UDPパケットを転送SOCKS5のプロキシサポート。

虽然HTTP代理有不同的使用模式,CONNECT方法允许转发TCP连接;然而,socks代理还可以转发UDP流量和反向代理,而HTTP代理不能。HTTP代理更适合HTTP协议,执行更高层次的过滤;socks不管应用层是什么协议,只要是传输层是TCP/UDP协议就可以代理。

socks5协议详解

socks5认证协议

image.png在客户端、服务端协商好使用用户名密码认证后,客户端发出用户名密码,格式为:

image.png

  • VER:鉴定协议版本
  • ULEN:用户名长度
  • UNAME:用户名
  • PLEN:密码长度
  • PASSWD:密码

服务器鉴定后发出如下回应:

image.png

  • VER:鉴定协议版本
  • STATUS:鉴定状态

其中鉴定状态 0x00 表示成功,0x01 表示失败。

socks5传输协议

创建与socks5服务器的TCP连接后,客户端需要先发送请求来协商版本及认证方式,格式为:image.png

  • VER:socks版本(在socks5中是0x05);
  • NMETHODS:在METHODS字段中出现的方法的数目;
  • METHODS:客户端支持的认证方式列表,每个方法占1字节。

服务器从客户端提供的方法中选择一个最优的方法并通过以下消息通知客户端(贪心算法:双方都支持、安全性最高):

image.png

  • VER:socks版本(在socks5中是0x05);
  • METHOD:服务端选中的方法(若返回0xFF表示没有方法被选中,客户端需要关闭连接);

METHOD字段的值可以取如下值:

  • X’00’ NO AUTHENTICATION REQUIRED
  • X’01’ GSSAPI
  • X’02’ USERNAME/PASSWORD
  • X’03’ to X’7F’ IANA ASSIGNED
  • X’80’ to X’FE’ RESERVED FOR PRIVATE METHODS
  • X’FF’ NO ACCEPTABLE METHODS

之后客户端和服务端根据选定的认证方式执行对应的认证。认证结束后客户端就可以发送请求信息(如果认证方法有特殊封装要求,请求必须按照方法所定义的方式进行封装)。

socks5请求格式:

image.png

  • VER:socks版本(在socks5中是0x05)
  • CMD:SOCK的命令码:
    • CONNECT X’01’
    • BIND X’02’
    • UDP ASSOCIATE X’03’
  • RSV:保留字段
  • ATYP:地址类型:
    • IP V4地址: X’01’
    • 域名地址: X’03’
    • IP V6地址: X’04’
  • DST.ADDR:目的地址

  • DST.PORT:目的端口

服务器按以下格式回应客户端的请求:

image.png

  • VER:socks版本(在socks5中是0x05)
  • REP:应答状态码:
    • X’00’ succeeded
    • X’01’ general socks server failure
    • X’02’ connection not allowed by ruleset
    • X’03’ Network unreachable
    • X’04’ Host unreachable
    • X’05’ Connection refused
    • X’06’ TTL expired
    • X’07’ Command not supported
    • X’08’ Address type not supported
    • X’09’ to X’FF’ unassigned
  • RSV:保留字段(需设置为X’00’)
  • ATYP:地址类型:
    • IP V4 address: X’01’
    • DOMAINNAME: X’03’
    • IP V6 address: X’04’
  • BND.ADDR:服务器绑定的地址
  • BND.PORT:服务器绑定的端口

如果被选中的方法包括有认证信息的封装、完整性和/或机密性相关检查,则server端在发送响应包时也需要把这些响应消息封装进去。

SOCKS相关工具

SOCKS服务器

部分SOCKS服务器软件:

SOCKSクライアント

組み込みアプリケーションは、通常の状況下で、SOCKSプロトコルをサポートします。

クライアント 許します リリース日 プラットフォーム サポート契約
ダンテの顧客 BSD / CMU 1.1.18 09/2005 Linuxの V4、V5
FreeCap GPL 3.18 02/2005 ウィンドウズ -
ハミングバード靴下 - - - ウィンドウズ -
ProxyCap - 2.03 - ウィンドウズ -
SocksCap 非商用家庭での使用 - - - V5
スーパーSocks5Cap - 1.5.3 - ウィンドウズ -
tsocks GPL 1.8 10/2002 - -
ナイロン - - 06/2003 OpenBSDの -

Pythonの実現SOCKS5プロキシ

便宜上、我々は直接でのpythonを使用しSocketServer、ライブラリ、次の手順では、SOCKS5プロキシサーバーを作成したマシンで直接実行することができます:

import socket, sys, select, SocketServer, struct, time class ThreadingTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): pass def handle_tcp(sock, remote): fdset = [sock, remote] while True: r, w, e = select.select(fdset, [], []) if sock in r: if remote.send(sock.recv(4096)) <= 0: break if remote in r: if sock.send(remote.recv(4096)) <= 0: break class Socks5Server(SocketServer.StreamRequestHandler): def handle(self): try: print('socks connection from ', self.client_address) sock = self.connection # 1. Version sock.recv(262) sock.send(b"\x05\x00"); # 2. Request data = self.rfile.read(4) mode = ord(data[1]) addrtype = ord(data[3]) if addrtype == 1: # IPv4 addr = socket.inet_ntoa(self.rfile.read(4)) elif addrtype == 3: # Domain name addr = self.rfile.read(ord(sock.recv(1)[0])) port = struct.unpack('>H', self.rfile.read(2)) reply = b"\x05\x00\x00\x01" try: if mode == 1: # 1. Tcp connect remote = socket.socket(socket.AF_INET, socket.SOCK_STREAM) remote.connect((addr, port[0])) print('Tcp connect to', addr, port[0]) else: reply = b"\x05\x07\x00\x01" # Command not supported local = remote.getsockname() reply += socket.inet_aton(local[0]) + struct.pack(">H", local[1]) except socket.error: # Connection refused reply = '\x05\x05\x00\x01\x00\x00\x00\x00\x00\x00' sock.send(reply) # 3. Transfering if reply[1] == '\x00': # Success if mode == 1: # 1. Tcp connect handle_tcp(sock, remote) except socket.error: print('socket error') def main(): server = ThreadingTCPServer(('', 1080), Socks5Server) server.serve_forever() if __name__ == '__main__': main() 

クライアントの実装コード:

import socket, socks, requests def main(): socks.set_default_proxy(socks.SOCKS5, "127.0.0.1", 1080) socket.socket = socks.socksocket print(requests.get('http://127.0.0.1:1080').text) if __name__ == '__main__': main() 

リファレンス

 
 
 

おすすめ

転載: www.cnblogs.com/jinanxiaolaohu/p/11283971.html
おすすめ