SOCKS:用于穿越防火墻的TCP代理協(xié)議
Ying-Da Lee
NEC 系統(tǒng)實驗室主要的技術(shù)負(fù)責(zé)人,CSTC
ylee@syl.dl.nec.com
SOCKS最初由David Koblas開發(fā)并且后來被我改進成當(dāng)前正在運行的版本—版本4。它用于一臺安裝了防火墻主機上使得用戶應(yīng)用協(xié)議可以透明的穿過防火墻。因為這個協(xié)議決定于應(yīng)用協(xié)議,所以它能夠(已經(jīng))用于很多的服務(wù),如telnet,ftp,finger,whois,gopher,WWW等等。在TCP協(xié)議的開始階段可以使用訪問控制;其后服務(wù)只能在客戶端和應(yīng)用服務(wù)器之間傳遞數(shù)據(jù),這樣就可以是傳輸消耗降到最小。因為SOCKS更本不需要知道任何應(yīng)用協(xié)議本身,所以他可以很容易的提供加密功能,使得消息在有監(jiān)控者的信道中能安全的傳輸。
SCOKS定義了兩個操作:CONNECT和BIND。
1) CONNECT
客戶端會和SOCKS服務(wù)器建立連接并且當(dāng)它想和應(yīng)用服務(wù)器建立連接時會發(fā)送一個CONNECT請求。客戶端的請求包中有目的主機的IP地址,端口號碼,和userid(譯者注:作為一個特殊的名稱沒有翻譯)。包格式如下:
+----+----+----+----+----+----+----+----+----+----+....+----+
| VN | CD | DSTPORT | DSTIP | USERID |NULL|
+----+----+----+----+----+----+----+----+----+----+....+----+
各段為: 1 1 3 4 長度可變 1
VN表示SCOKS協(xié)議的版本號碼,在本版本是應(yīng)該為4。CD表示SOCKS的命令碼,CONNECT命令為1。NULL是所有bit都為0的一個字節(jié)。
SCOKS服務(wù)器會通過檢查一個由源IP地址,目的IP地址,目的端口號碼,userid,和被包含在經(jīng)過商議的IDENT中的信息所組成的聯(lián)合標(biāo)識符(比較RFC1413)來確定請求是否被允許。如果請求通過,則SCOKS會建立一個和目的主機端口的連接。當(dāng)和目的主機的鏈接被建立,或請求被拒絕,或操作失敗時,會給客戶端返回一個包。如下
+----+----+----+----+----+----+----+----+
| VN | CD | DSTPORT | DSTIP |
+----+----+----+----+----+----+----+----+
各段為 1 1 2 2
VN是返回的版本編碼,這里為0。CD是表示下列結(jié)果之一的編碼:
90: 請求被接受
91: 請求被拒絕或者失敗了
92: 請求被拒絕因為不能和客戶端提供的IDENT建立連接。
93: 請求被拒絕因為客戶端和IDENT代表了兩個不同的用戶。
剩下的部分被忽略了。
在SCOKS服務(wù)器告訴客戶端請求被拒絕或失敗后,會馬上關(guān)閉連接。對于一個成功的請求,SCOKS服務(wù)器會準(zhǔn)備在兩個方向傳遞信息。這樣可以使客戶端像直接連上了應(yīng)用服務(wù)器一樣進行I/O操作。
2) BIND
當(dāng)客戶端準(zhǔn)備接收來自應(yīng)用服務(wù)器的連接時,它會像SCOKS服務(wù)器附送一個BIND請求。這會發(fā)生在和應(yīng)用服務(wù)器的主要連接被CONNECT建立后。往往,這個部分按順序會有以下的步驟:
-bind(): 獲得一個套接字
-getsockname(): 得到套接字中的IP地址和端口號碼
-listen(): 準(zhǔn)備接受來自應(yīng)用服務(wù)器的連接。
-使用主連接告訴應(yīng)用服務(wù)器連接的IP地址和端口號碼。
-accept(): 接收來自應(yīng)用服務(wù)器的鏈接。
使用SCOKS的BIND操作的只要目的是為了支持這樣一個順序,套接字在SCOKS服務(wù)器上使用,而不是在客戶端上。
客戶端的請求包中有應(yīng)用服務(wù)器的IP地址,主連接使用的目的端口號,和userid。
+----+----+----+----+----+----+----+----+----+----+....+----+
| VN | CD | DSTPORT | DSTIP | USERID |NULL|
+----+----+----+----+----+----+----+----+----+----+....+----+
各段為:1 1 2 4 長度可變 1
VN是4,表示SCOKS協(xié)議的版本。CD一定是2,代表這是BIND請求。
SCOKS服務(wù)器使用客戶端信息確定請求是否被接受。服務(wù)器返回給客戶端的包的格式和CONNECT請求的返回包一樣,如,
+----+----+----+----+----+----+----+----+
| VN | CD | DSTPORT | DSTIP |
+----+----+----+----+----+----+----+----+
各段為:1 1 2 4
VN是返回的版本編碼,這里為0。CD是表示下列結(jié)果之一的編碼:
90: 請求被接受
91: 請求被拒絕或者失敗了
92: 請求被拒絕因為不能和客戶端提供的IDENT建立連接。
93: 請求被拒絕因為客戶端和IDENT代表了兩個不同的用戶。
無論如何,對于一個被接受的請求(CD是90),DSTPORT和DSTIP域是有意義的。那樣的話,SCOKS服務(wù)器會等待一個進入的連接,并把套接字中的端口號和IP地址分別放到DSTPORT和DSTIP中發(fā)送給客戶端。如果返回的DSIP是0(常量INADDR_ANY的值),則客戶端會用連接著的SOCKS服務(wù)器的IP地址替換它。(這個僅會發(fā)生在SOCKS服務(wù)器不是多用戶主機的情況) 典型的情況是,同時有兩個以上的應(yīng)用程序需要經(jīng)由服務(wù)器而導(dǎo)致getsockname()的并發(fā)調(diào)用。應(yīng)用協(xié)議應(yīng)當(dāng)提供一種將兩種不同信息從客戶端發(fā)送到服務(wù)器的方法,使得它可以初始化與SCOKS服務(wù)器的連接,而不是像平時一樣和應(yīng)用服務(wù)器的連接。
當(dāng)來自應(yīng)用服務(wù)器的預(yù)期連接被建立后,SCOKS服務(wù)器會返回第二個包給客戶端。SOCKS服務(wù)器檢查源主機的IP地址,并與客戶端的BIND請求的DSIP域比較。如果雙方不匹配,第二個返回包中的CD域會被設(shè)置為91并且SOCKS服務(wù)器會關(guān)閉和兩邊連接。如果匹配的話,返回包的CD域會被設(shè)置為90,并且SCOKS服務(wù)器將在它的兩個連接間傳遞信息。從這以后,客戶端就可以和SCOKS服務(wù)器進行I/O操作,就好象直接連上了應(yīng)用服務(wù)器。
對于CONNECT和BIND操作,服務(wù)器都為建立連接設(shè)置了時間限制(當(dāng)前的CSTC實現(xiàn)將時限設(shè)為2分鐘)。如果時限到了后連接還沒有建立,服務(wù)器會關(guān)閉和客戶端的連接并且放棄。
SOCKS 4A:SCOKS 4協(xié)議的簡單擴展
Ying-Da Lee
yingda@best.com or yingda@esd.sgi.com
請首先閱讀描述4號協(xié)議版本的SOCKS4.protocol。這個擴展允許沒有能力解析所有域名的主機使用SCOKS。
在版本4中,客戶端會發(fā)送如下的包給服務(wù)器,請求CONNECT或者BIND操作。
+----+----+----+----+----+----+----+----+----+----+....+----+
| VN | CD | DSTPORT | DSTIP | USERID |NULL|
+----+----+----+----+----+----+----+----+----+----+....+----+
各段為 1 1 3 4 長度可變 1
VN是SCOKS協(xié)議的版本號,在這個版本中為4.CD是請求命令的代碼,1代表CONNECT命令,2代表BIND命令。NULL是所有bit都為0的一個字節(jié)。
對于版本4,如果客戶端不能把目的主機的域名解析成IP地址。那么它會將DSIP的前3個字節(jié)設(shè)置為空并將最后一個字節(jié)設(shè)置成一個不為0的值。(這樣的IP地址符合I0.0.0.x的形式,它被IAIN(互聯(lián)網(wǎng)數(shù)字權(quán)威分配組織)認(rèn)為是一個不被接受的目的地址,因此就不會發(fā)生客戶端無法解析主機域名的情況了)緊跟著的userid后面有一個空字節(jié)作為結(jié)束,客戶端必須發(fā)送目的域名并以一個空字符結(jié)束它。這個方法用于CONNECT和BIND操作。
一個使用SCOKS4協(xié)議的服務(wù)器必須檢查請求包的DSIP域。如果地址是0.0.0.x,x不為0的形式,服務(wù)器必須降包中的userid域讀出。如果服務(wù)器可以的話,它將解析域名并與目的主機建立連接。
服務(wù)器中繼程序可以將它不能解析的域名傳送給下一跳的SCOKS服務(wù)器。