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