穿越中間設備(middleboxes)的P2P通訊

穿越中間設備(middleboxes)的P2P通訊
   
本篇備註的狀態
 
    該文檔是一個internet草案,遵守RFC2016第10節的規定。Internet草案是IETF和他的工作組的文檔。注意,其他團體或組織也可以發表工作文檔爲Internet草案。
  
   Internet-草案是一種草案文檔,有效期最多是6個月。他可以隨時被其他文檔更新,替換或者廢除。把Internet草案作爲資料引用或者參考而不是在他的上面進一步工作是不適當的。
 
    這份internet草案可以通過這個地址獲得:http://www.ietf.org/1id-abstracts.html
 
    internet草案的目錄列表可以從這裏獲得:http://www.ietf.org/shadow.html
   
   發佈本篇文檔不受任何限制。
 
 版權注意事項
     Copyright (C) The Internet Society (2003). All Rights Reserved.
 
 
   
摘要
 
    本草案介紹了當前p2p應用程序在有中間設備進行通訊時的方法,這些中間設備比
   如:防火牆、網絡地址轉換器(NAT)。此外,本篇還提供給應用程序設計者和中間
   設備的實現者一些建議,使得他們能夠即時的廣泛的確定p2p的應用程序需要何種
   具體的代理、中繼協議。
 
 
目錄
 
 
   1. 介紹 ………………………………………………………………….……………………2
   2. 術語 ……………………………………………………………………………………….3
   3. P2P穿越中間設備通訊的技術 …………………………………………………………..6
       3.1. 中繼 ………………………………………………………………………………..6
       3.2. 反向連接 …………………………………………………………………………..7
       3.3. UDP 穿孔 …………………………………………………………………………8
             3.3.1. 對端在不同的NATs背後 ……………………………………….………8
             3.3.2. 對端在相同的NATs背後 …………………….………………….…..…9
             3.3.3. 對端由多個NATs分開 ………………………………………….…….11
             3.3.4. 一致端口綁定 …………………………………………………….…....11
       3.4. UDP 端口號預測 ………………………………………………………….…….11
       3.5. 同時打開TCP …………………………………………………………….………13
   4. 應用程序設計指南 …………………………………………………………….…..……13
       4.1. 有中間設備的怎麼做 …………………………………………………….…...…..13
       4.2. 在同一個NAT背後的應用程序 ………………………………………….………13
       4.3. 發現對端 ….……………………………………………………………….………13
       4.4. TCP P2P 應用程序 ………………….……………………………….……………13
       4.5. 使用midcom協議 ………………….……………………………….…….………14
   5. NAT設計指南 ……………………………………………………….………….………14
       5.1. 不贊成使用對稱NATs(symmetric NATs) ……………………….….…….………15
       5.2. 給對稱NATs設備添加Cone-NAT支持 ……………………….….…….………15
       5.3. 維護UDP端口綁定的一致端口 ……………………………….…...…….……...15
             5.3.1. 保留端口號 ………………………………………….…...……….……15
       5.4. 爲UDP端口維護一致的端口綁定 ……………………………….…...….………16
       5.5. P2P應用程序大的超時時間 …..…………………………….…….………………16
   6. 安全考慮 ……………………………………………………………………...…………16
 
 
 
 
1. 介紹
 
 
 
   當前的internet到處都設有中間設備(middleboxes),比如網絡地址轉換器,這主要是由於IPv4的地址空間耗盡所引起的。然而,由中間設備建立起來的非對稱的連通體系給p2p應用程序和協議帶來了獨特的問題,比如電信會議和多人在線遊戲。由於NAT可能頻繁的用於和IPv4的兼容上,這些問題也可能存在於IPv6的世界。就算NAT不再需要,防火牆也勢必存在。
 
 
   當前的中間設備主要是爲了典型的C/S模型設計的,中間設備中的匿名客戶端來訪問有固定IP的server和DNS。許多的中間設備完成了這種非對稱連接。私有網絡中的主機能夠發出一個初始連接到公網主機,但是外部主機不能初始發出對內網主機的連接,除非由中間設備的管理員配置過了。在普通的NAPT情況下,一個內網的Client不具有在公網唯一的IP地址,而是和同在一個私有網絡中的主機共享一個IP地址,這種共享由NAPT來維護。這種對內網主機的匿名和不可訪問性,對客戶端軟件比如web瀏覽器卻不是問題,因爲他們僅僅要需要初始向外的連接。不可訪問性有時候被視爲隱私的好處。
 
 
   然而,在p2p模型中,被視爲client的internet主機需要彼此直接建立連接會話。發起者和迴應者也許在不同的中間設備的後面,可能既沒有固定的IP,也沒有公共網絡中其他的存在形式。比如一個普通的在線遊戲體系結構是參與主機來連接已知的服務器來初始化和其他的一些管理動作。緊接着,主機間建立了直接的連接,以便遊戲期間快速有效的更新。類似的,一個文件共享應用程序也是連接已知的服務器進行資源查找,但對數據傳送則建立直接的連接。中間設備產生了P2P連接的問題在於:中間設備背後的主機沒有在internet上永久可用的端口和其他的客戶建立直接的連接。RFC 3235 [NAT-APPL]簡要的描述了這個問題,但是沒有提供一般的解決方案。
 
 
   這篇文檔中我們將提出p2p/中間設備問題的2種解決方法。首先我們概述p2p應用程序在當前的中間設備中已知的工作方法。第二,我們提出一些使得能夠在當前的中間設備佈置情況下更健壯的應用程序設計指導。進一步,我們提出未來中間設備設計指導,使得他們更有效的支持p2p應用程序。我們的目標是使得需要穿越中間設備的應用程序及時而廣泛。
 
 
2. 術語
 
 
 
本節中我們提出一些中間設備的術語,主要關注產生P2P應用程序問題的2種類型的中間設備。
 
 
 
 
   防火牆/Firewall
      防火牆限制了內網和外網的通訊,通常是丟棄認爲是未授權的包。防火牆檢查      但是不修改穿過邊界包的IP地址和TCP/UDP端口信息。
 
 
  網絡地址轉換器 /Network Address Translator (NAT)
      網絡地址轉換器不但檢查而且修改穿越邊界包的頭信息,運行在NAT設備後面的      許多主機來共享較小數量的公網IP地址(通常是一個)。
 
 
   網絡地址轉換器有2中形式:
 
 
   基本NAT/Basic NAT
      當數據包穿過NAT時,基本NAT映射內部主機的私有IP爲公網IP,不改變TCP/UDP      端口號。僅僅當基本NAT有一個公網IP地址池,它才發生效用,從池中做代表內部主機的地址綁定。
 
 
   網絡地址/端口轉換器(NAPT)
      現在最普通的端口轉換器,他檢查並且修改穿越邊界包的IP地址和TCP/UDP端口      號,多個內部主機同時共享一個公網IP。
 
 
   參考[NAT-TRAD]和[NAT-TERM]取得關於NAT分類和術語的更多信息。進一步劃分NAPT的術語在最近的[STUN]文檔中。當內部主機通過NAPT打開一個向外的TCP或UDP會話時,NAPT分配給這個會話一個公共IP地址和端口,以便接下來外部節點的響應包能夠被 NAPT接收、解釋、轉發給內部節點。效果就是NAPT建立了一個如下的端口綁定:(private IP addr, private port number)和(public IP addr, public port number)。端口綁定定義了地址轉換,NAPT將完成這個會話過程。一個和p2p應用程序相關的問題是當同一個內部主機同時發起和外網多個主機進行會話時,NAT做了些什麼?
 
 
   錐形NAT/Cone NAT
      在建立了(private IP, private port)和(public IP, public port)這個端口綁定之後,錐形NAT對來自同一個私有ip地址和端口的應用程序發起的一系列的會話進行端口重用,只要有一個會話還在,綁定的端口就保留。
    
      比如,設Client A在下面的模型中通過一個Cone NAT同時發起2個向外的會話。      他們都是來自同一個內部節點(10.0.0.1:1234)到2個不同的外部服務器S1和S2。(譯註:這裏10.0.0.1:1234同時發起2個到外部server的連接是可能的,首先在於這2個可能是2個不同的協議,其次同一個地址同一個協議也可能將2個socket綁定到同一個端口上面,比如每一個VStudio IDE進程就會在本機的同一個UDP端口建立一個socket)。cone NAT只分配一個節點映射(endpoint tuple)給這兩個會話,155.99.25.11:62000,確保了client端的端口號的一致性在地址解析時得到維護。由於basic NATs和防火牆在包流過中間設備時不修改端口號,所以他們可以看作是cone NATs的退化形式。
 
 
           Server S1                         Server S2
        18.181.0.31:1235                   138.76.29.7:1235
               |                                |
               +-----------------------+----------------------+
|
          ^ Session 1 (A-S1) ^  |      ^ Session 2 (A-S2) ^
          | 18.181.0.31:1235 |   |      | 138.76.29.7:1235 |
          v 155.99.25.11:62000 v   |      v 155.99.25.11:62000 v
                                |
                             Cone NAT
                             155.99.25.11
                                |
          ^ Session 1 (A-S1) ^ |      ^ Session 2 (A-S2) ^
          | 18.181.0.31:1235 |  |      | 138.76.29.7:1235 |
          v   10.0.0.1:1234    v |      v 10.0.0.1:1234    v
                                |
                             Client A
                           10.0.0.1:1234
 
 
   對稱NAT / Symmetric NAT
      作爲對比,對稱NAT在內外網端口(private IP, private port) and (public IP, public port)綁定時並不維護一致的綁定端口。相反,他會給每一個新的會話分配一個新的端口。比如,Client A和上面一樣發起2個和s1,s2的會話連接,對稱NAT可能會把session 1映射成155.99.25.11:62000,把session 2映射成這樣155.99.25.11:62001。NAT能夠區分2個不同的會話,甚至當client應用程序的節點標識被丟失時,因爲會話涉及的外部節點不同。
 
 
           Server S1                        Server S2
        18.181.0.31:1235                   138.76.29.7:1235
               |                                |
               +-----------------------+----------------------+
                                |
          ^ Session 1 (A-S1) ^  |      ^ Session 2 (A-S2) ^
          | 18.181.0.31:1235 |   |      | 138.76.29.7:1235 |
          v 155.99.25.11:62000 v   |      v 155.99.25.11:62001 v
                                |
                           Symmetric NAT
                            155.99.25.11
                                |
          ^ Session 1 (A-S1) ^ |      ^ Session 2 (A-S2) ^
          | 18.181.0.31:1235 |   |      | 138.76.29.7:1235 |
          v 10.0.0.1:1234    v   |      v 10.0.0.1:1234    v
                                |
                             Client A
                            10.0.0.1:1234
 
 
   cone NAT相對於symmetric NAT一樣會產生TCP and UDP的擁塞問題。
 
 
   根據NAT能夠有多少的自由接收已經建立連接(public IP, public port)的輸入數據,Cone NAT可以被進一步劃分。這種分類通常僅用於UDP方式數據交換,因爲NAT和防火牆會無條件拒絕tcp連接,除非在其他地方有特別的設置。
 
 
   完全的(Full) Cone NAT
      在爲一個向外的會話建立了公/私端口綁定之後,full cone NAT隨後將接收來自公網上任何終端節點相應端口的輸入通訊。Full cone NAT有時也稱爲“混雜”(promiscuous)NAT.
 
 
   受限的(Restricted) Cone NAT
      受限的cone NAT僅僅在外部輸入數據包的端口匹配內部主機曾經發給外部數據時使用的映射端口才轉發給內部主機。受限的cone NAT精簡採用了防火牆的原則,通過限制輸入數據包爲已知的外部IP地址,來拒絕一些外部的主動連接請求。
 
 
   端口受限(Port-Restricted) Cone NAT
      反過來,對端口受限(Port-Restricted) Cone NAT,如果外部ip地址和端口匹配那些內部主機曾經向外發包在NAT上映射的端口,他就將這個輸入包轉發給相應的內部主機。當端口受限Cone NAT在維護這種穿越映射所需的端口身份表時,他提供了和對稱(symmetric)NAT一樣的對(未有映射的)主動的外部請求有同樣的保護。
 
 
   最後,在這篇文檔中我們定義一些新的術語來分類中間設備的P2P相關的行爲。
   P2P-應用程序
      如本篇提到的,P2P應用程序是這樣的程序:每個p2p的參與者在服務器上註冊,接下來,在私有或者公共的終端建立對等(peering)的會話。
 
 
   P2P-中間設備(Middlebox)
      P2P-中間設備(Middlebox)就是允許應用程序穿越的中間設備。
 
 
   P2P-防火牆(firewall)
      P2P-firewall是一個P2P-中間設備(Middlebox),他提供防火牆功能,但是不做地址轉換。
 
 
   P2P-NAT
      P2P-NAT是P2P-中間設備(Middlebox),他提供NAT功能,並且也提供防火牆功能。至少,P2P-Middlebox要爲UDP通訊實現Cone NAT功能,以允許應用程序使用UDP穿孔 (UDP hole punching technique)技術建立健壯的P2P連接。
 
 
   迴路解釋/Loopback translation
      當一個NAT設備的內部主機使用公共地址(譯註:就是那個內部主機對外表現的      地址)試圖連接在同一個NAT設備後的內部主機,NAT設備會按照如下做2次解釋("Twice-nat" translation):原主機私有終端地址被解釋成公共終端地址,在包被轉發以前,目標主機的公共終端地址又被解釋成私有終端地址,我們稱由NAT完成的這種解釋爲“迴路解釋”(Loopback translation)。(譯註:這裏實際是說NAT在轉發數據時如果會先查一下,看看目的終端的公共地址是不是自己,如果是,就表示源、目的主機都在本NAT裏面。)
 
3. 跨越中間設備P2P通訊的技術
 
 
 
   本節從應用程序和協議設計的觀點,來詳細的回顧當前p2p跨越中間設備通訊實現的技術。
 
 
3.1. 中繼/Relaying
 
 
   在有中間設備的p2p通訊的實現方法中,最可靠,但缺乏效率的方法是:使P2P通訊看起來象通過中繼的C/S網絡。比如,2個客戶端A和B,初始發起了TCP或UDP的連接到一個已知的有永久IP地址的server S。然而,客戶端是分居在兩個私有網絡中的,他們各自的中間設備阻止了一方直接向另一方發起連接。
 
 
                         Server S
                            |
            +----------------------+----------------------+
            |                                |
          NAT A                           NAT B
            |                                |
         Client A                          Client B
 
 
   兩個客戶端可通過server S來中繼他們的消息,而不是試圖直接連接。比如,要發消息給B,A只要把消息通過已經建立的連接發給S,然後S使用已經建立的連接發給B。
 
 
   這個方法有他的優點,只要雙方都連上了server,他總能工作。他的明顯的不足在於:他無謂的消耗了服務器的處理能力和網絡帶寬,而且,即使和服務器連接的很好,雙方的通訊延時也增加了。TURN 協議 [TURN] 實現了一種相對可靠的中繼方式。
 
 
3.2. 反向連接/Connection reversal
 
 
   如果僅有一個客戶端在中間設備後面,那麼第二項技術就可行了。比如,客戶端A在一個NAT後面,而B有一個全球可路由的IP地址,如下圖:
 
 
                        Server S
                    18.181.0.31:1235
                            |
                            |
            +----------------------+----------------------+
            |                                |
          NAT A                             |
    155.99.25.11:62000                        |
            |                                |
            |                                |
         Client A                          Client B
      10.0.0.1:1234                      138.76.29.7:1234
 
 
   客戶端A的私有IP爲10.0.0.1,應用程序使用TCP的1234端口。這個客戶端和IP地址爲18.181.0.31,端口爲1235的server建立了連接。NAT分配了62000TCP端口在他的公網IP155.99.25.11上,作爲一個臨時的終端地址爲A和S的會話提供服務,因此,S就認爲A在155.99.25.11:62000上。然而,對客戶端B,他有自己的永久IP138.76.29.7,且B的p2p應用程序正在TCP端口1234上Listen。
 
 
   現在假設客戶端B要發起一個和A的初始連接會話。B首次嘗試連接A要麼在A自認   爲的地址10.0.0.1:1234,要麼在server S看到的155.99.25.11:62000。然而,這兩種情況都要失敗。在第一種情況下,到10.0.0.1的包簡單的被網絡丟棄,因爲10.0.0.1不是一個可以路由的公網地址。在第二種情況,來自於B的TCP SYN請求會直接到達A的NAT的62000端口,但是A的NAT會拒絕這個連接請求,因爲僅僅向外的連接才被許可。
 
 
   在試圖和A建立連接失敗後,B可以借用S來中繼一個給A的請求,告訴A做一個反向的到B的連接。A根據從S受到的這個請求,打開一個TCP連接到B的ip:port。A的NAT會許可這個連接,因爲他從防火牆內發起,並且B能夠收到這個連接,因爲他不在任何的中間設備後面。
  
   許多當前的P2P系統實現了這一技術。當然,他的主要限制在於:僅有一端在NAT後面的情況才適用,在越來越普遍的兩端都在NATs後面的情況,就不行了。
  
   因爲反向連接不是一般的解決方案,不推薦作爲一個主要策略。應用程序可以選擇進行反向連接,但是當正向和反向都失敗時,他應能回來再用其他的方法,比如通過中繼。
 
 
3.3. UDP穿孔(hole punching)
 
 
   第三種技術,也是本文主要的興趣之一,就是被稱爲UDP穿孔的技術。UDP穿孔依賴   於公共防火牆的屬性和Cone NATs許可適當設計的p2p程序來穿孔以穿越中間設備建立彼此的直接連接,即使當通訊雙方都在中間設備的後面。這項技術在RFC 3027的5.1節[NAT-PORT]有簡要的介紹,也在Internet的其他地方有非正式的描述[KEGEL], 並且被用在最近的一些協議種[TEREDO, ICE]。不幸的是,和他的名字所暗示的一樣,這個技術僅僅適用UDP。
 
 
   我們將要考慮2種具體的情況,和應用程序如何以優雅的設計來處理這兩種情況。在第一種情況中,代表了一種一般的情況,兩個要建立P2P通訊的客戶端被置於兩個不同的NATs之後。第二種情況是,兩個要建立P2P通訊的客戶端在同一個NATs的後面,但是未必知道他們的這個處境。
 
 
3.3.1. 兩端在不同的NATs之後
 
 
   假定clients A 和 B 都有自己的私有IP地址,並且在不同的NATs之後。在A,B,S上運行的應用程序都使用UDP的1234端口。A和B都已和S建立了UDP連接,使得NAT A爲A和S的會話分配了公網的UDP端口62000,NAT B爲B和S的會話分配了公網UDP端口31000。
 
 
                       Server S
                     18.181.0.31:1234
                            |
                            |
            +----------------------+----------------------+
            |                                |
          NAT A                            NAT B
    155.99.25.11:62000                    138.76.29.7:31000
            |                                |
            |                                |
         Client A                          Client B
      10.0.0.1:1234                       10.1.1.3:1234
 
 
   現在假定A要和B建立P2P的UDP連接。如果簡單的發給B的公網地址138.76.29.7:31000, 那麼NAT B通常會丟棄這個輸入信息(除非他是full cone NAT),因爲源地址和端口不是S的---這個始發向外已經建立的地址和端口, 同樣如果B簡單的向NAT A 發送一個UDP包,也會被NAT A 丟棄。
 
 
   然而,假定A向B的公網地址發一個UDP包,同時請求S要求B向A的公網地址發一個UDP包到A的公網地址。A向B的公網地址(138.76.29.7:31000)發送一個消息的同時導致NAT A爲這個新的A的私有地址到B的公網地址建立了一個會話(映射)。與此同時B到A的公網的消息在B的NAT B上建立了一個新的B的私有地址到A的公網地址(155.99.25.11:62000)的會話(映射),一旦這個新的UDP會話在兩端打開,A和B的通訊就可以直接建立,而不再需要S進行“介紹”的負擔。
 
 
   UDP穿孔技術有許多有用的特性。一旦在2箇中間設備背後的主機建立了P2P的UDP連接,這個連接的雙方都可以充當“介紹人”的角色來幫助對端主機和其他主機建立P2P連接,這樣可以最小化server來幫助建立初始連接的負荷。 應用程序不需要試圖去檢測他在什麼樣的中間設備背後,因爲如果一端或者兩端不在中間設備的後面,上層的程序依然能夠很好的建立P2P連接。穿孔技術甚至可以自動在有多層NATs的情況下工作,就是一端或者雙方都在兩層或者超個兩層的NATs後面的情況。
 
 
3.3.2. 雙端在同一個NAT之後
 
 
   現在考慮雙端在同一個NAT之後的情況(他們可能並不知道),這樣他們就在同一個私有的IP地址空間中。A和S建立了UDP會話,NAT分配了62000端口,B和S建立了UDP連接,NAT分配了62001端口。
 
 
                       Server S
                    18.181.0.31:1234
                           |
                           |
                         NAT
                A-S 155.99.25.11:62000
                 B-S 155.99.25.11:62001
                            |
            +----------------------+----------------------+
            |                               |
         Client A                         Client B
      10.0.0.1:1234                      10.1.1.3:1234
 
 
   假定A和B使用上面提到的UDP穿孔技術,通過S爲介紹人來建立P2P連接。然後A和B會知道彼此的公網IP地址和端口(由S獲得告知的),接着開始在那個公網IP和端口上發送UDP消息。只要NAT允許內網主機來開啓轉譯的和內網主機的會話,而不僅僅是和外部主機,兩個客戶端就可以建立彼此的通訊。我們稱這種情況爲“迴路解釋”(loopback translation),因爲包到達NAT被解釋,然後再回到了內網,而不是送到了公網。例如,當A發送一個UDP包給B的公網地址,包的源地址和端口是10.0.0.1:124,目的端口和地址是155.99.25.11:62001。NAT收到這個包,把他解釋爲源地址和端口是155.99.25.11:62000 (A的公網地址),目的地址和端口是10.1.1.3:1234,然後轉發給B。即使NAT支持“迴路解釋”,   很顯然,這種情況下的解釋和轉發都是不必要的,並可能增加A和B的潛在的對話同時加重了NAT的負擔。
 
 
   對這個問題的解決方法是直接轉發(straightforward)。當A和B通過S初始交換地址的時候,他們應該包括自己看到的自己的IP地址和端口和由server看到的自己的IP地址和端口。客戶端然後同時給這兩個地址發送數據,並使用第一個成功進行通訊的地址。如果兩個客戶端在同一個NAT的後面,那麼,直接發往私有地址的包會先到達,就產生了一個直接連接的通道,而與NAT無關了。如果兩個客戶端在不同的NATs後面,直接發往私有地址的包就根本不能到達,但客戶端將有希望通過各自的公網地址建立連接。然而,對這些包進行某種授權是重要的,因爲在不同NATs的情況中,A直接發往B私有地址的信息完全可能到達和A同一個私網的其他主機(or vice versa)。
 
 
3.3.3. 對端由多個NATs分開
 
 
   在某些涉及多個NAT設備的拓撲中,在沒有具體的拓撲的知識情況下,兩個客戶端不   可能建立起來最優的P2P路由。考慮下面的情況:
 
 
                        Server S
                     18.181.0.31:1234
                            |
                            |
                          NAT X
                  A-S 155.99.25.11:62000
                  B-S 155.99.25.11:62001
                            |
                            |
            +----------------------+----------------------+
            |                                |
          NAT A                           NAT B
    192.168.1.1:30000                   192.168.1.2:31000
            |                                 |
            |                                 |
         Client A                           Client B
      10.0.0.1:1234                       10.1.1.3:1234
 
 
   假定NAT X是一個由ISP佈置的大的工業的NAT,來爲許多客戶提供服務,NAT A和NAT B是較小的客戶NAT gateways。僅僅server S和NAT X有全球可路由的IP地址。NAT A和NAT B使用的公網IP地址實際上是在ISP的私有IP地址範圍,而客戶端A,B又分別在NAT A和NAT B的私有地址範圍。每一個客戶端象前面一樣初始發出一個到S的連接,致使NAT A和NAT B分別創建了一個公/私地址轉換,又使得NAT X爲每一個會話創建了一個公/私地址轉換。
 
 
   現在假定A和B試圖建立一個P2P UDP連接。最優的情況是,A發送一個消息給B在NAT B上面的公網地址(譯註:這裏沿用前面的譯法,實際上是指映射後的地址),即在ISP的地址範圍192.168.1.2:31000,對B要給A發送消息應該在192.168.1.1:30000。不幸的是,A和B也許沒有辦法知道這些地址,因爲S僅僅看到一個全局的公共地址,即155.99.25.11:62000 和 155.99.25.11:62001。即使A和B有辦法知道這些地址,仍然不能保證他們(這些地址)可用,因爲ISP私有地址範圍可能會和客戶端私有地址範圍衝突。此時,客戶端沒有選擇,只能依賴由S端看到的全局的公網地址來進行P2P通訊,並依靠NAT X進行“迴路解釋”(loopback translation)。
 
 
3.3.4. 一致端口綁定/Consistent port bindings
 
 
   這種穿孔技術有一個主要的警告:僅僅在雙方NATs是cone NATs的時候,他才起作用,或者是非NAT 防火牆(non-NAT firewalls),只要那個UDP端口在使用,他就對特定的(私有IP, 私有UDP端口)和(公共IP, 公共UDP端口)維護了一致的端口綁定。像對稱NAT那樣爲每次會話分配一個新的公網端口的話,就會使得UDP應用程序不能重用已經建立的解釋來與不同的外部主機通訊。由於cone NATs是很普遍的,所以UDP穿孔技術有相當廣泛的應用。不過,有的NATs還是對稱的,他們不支持這項技術。
 
 
3.4. UDP端口號預測
   上面討論的UDP穿孔技術存在不同的情況,就是允許P2P會話建立在當前的一些對稱NAT上。這種技術有時被稱爲"N+1"技術[BIDIR],並由Takeda [SYM-STUM]詳細討論了。這種方法通過分析NAT的行爲來工作,並且試圖猜測NAT將要爲新會話分配的端口號。再次,我們來看下面的情況,A和B與server S建立了UDP連接:
 
 
                           Server S
                        18.181.0.31:1234
                              |
                              |
              +----------------------+---------------------+
              |                               |
       Symmetric NAT A                Symmetric NAT B
   A-S 155.99.25.11:62000               B-S 138.76.29.7:31000
              |                               |
              |                               |
           Client A                          Client B
        10.0.0.1:1234                       10.1.1.3:1234
 
 
   NAT A 已經分配了一個UDP端口62000給A和S的會話,NAT B 分配了31000端口給B和S的會話。通過S,A和B知道了彼此的公網地址和端口號。現在A向138.76.29.7:31001發送UDP消息(注意,端口號加1了),B同時給155.99.25.11:62001發送一個包。如果A和B的NAT都是順序分配新會話的端口號,並且如果從A-S和B-S初始會話還沒有多少時間的話,那麼一個A和B的雙向連接應該可以建立了。A到B的消息使得NAT A打開了一個新的會話,A希望得到NAT A分配62001這個端口號,因爲62001是剛纔爲A-S分配的端口號62000的下一個端口。類似的,B到A的消息使得NAT B建立了一個新的會話,同樣B希望得到31001這個端口號。如果雙方都正確的猜到了各自NAT將要爲新會話分配的端口號,如下圖的雙向連接就應該能夠被建立起來:
 
 
 
 
 
 
                           Server S
                        18.181.0.31:1234
                              |
                              |
              +----------------------+---------------------+
              |                               |
            NAT A                          NAT B
   A-S 155.99.25.11:62000               B-S 138.76.29.7:31000
   A-B 155.99.25.11:62001               B-A 138.76.29.7:31001
              |                                |
              |                                |
           Client A                          Client B
        10.0.0.1:1234                      10.1.1.3:1234
 
 
   顯然,有很多的原因可能導致這個小技巧失敗。如果預測的端口號已經由一個不相關的會話使用了,那麼NAT會就會跳過這個端口,連接就會失敗。如果NAT有時候或者總是不是按順序選擇端口號,這個小技巧也會失敗。如果NAT A(或者B)後面的其他主機在A(B)和S建立連接之後,又在A(B)向B(A)發送消息之前,又打開了一個新的和S的會話,那麼這個不相關的客戶端就會不經意的“竊取”到(我們)想要的端口號(的數據)。因此,這個技巧在雙方的NAT負荷較重的時候,很可能不正常。
 
 
   由於實際中,實現這個小伎倆的P2P程序也需要在雙方都是cone NATs,或者一方是cone NATs,另一方是對稱NAT時,所以應用程序仍然要檢測雙方的NAT的類型,並且修改應用程序到相應的行爲下工作,增加了算法的複雜性,和網絡的脆弱性(譯者:作者可能指信息會被其他人“竊取”這個問題)。最後,在多級NAT,且離客戶端最近的NAT是對稱NAT的時候,通過猜測端口的技術就沒有機會成功了。由於種種這些原因,不推薦新的應用程序實現這個技術,這裏做介紹,是出於歷史和資料性的目的。
 
 
3.5. 同時打開TCP/Simultaneous TCP open
 
 
   有一個方法可以用來在雙方都在中間設備(middleboxes)後面時建立P2P TCP連接。大多數的TCP會話始於一端發出一個SYN包,對端迴應一個SYN-ACK包。然而,如果雙方同時發給對方發送SYN包,再回復一個ACK包,就有可能建立一個合法的TCP會話。這個過程被稱爲“同時打開”(simultaneous open)。
 
 
   如果中間設備收到一個外面的TCP SYN包,來試圖初始化一個輸入(incoming)的TCP連接,中間設備通常會丟棄SYN包以拒絕這個連接,或者發送TCP RST(connection reset)包,然而,如果到達的SYN包源、目的地址和端口讓中間設備以爲他已經是活動的話,中間設備就會允許這個包通過。尤其是中間設備剛剛看到並且傳送了一個有同樣地址和端口的向外的SYN包,那麼他會認爲這個會話是活動的並放行這個incoming SYN。如果A和B都能夠正確的預測到中間設備將要分配給下一個向外的TCP連接的端口號,並且雙方及時的向對方發出一個TCP連接,以便客戶端的向外的SYN包在對方的SYN到達自己的中間設備之前穿過自己的中間設備,這樣的話一個P2P的TCP連接就建立起來了。
 
 
   不幸的是,這個小技術也許很脆弱且時間比上面提到的UDP端口預測技術嚴格。首先,除非雙方的中間設備僅是防火牆或者由cone NAT實現,否則所有的事情---預測每一邊NAT分配新會話的端口,都可能是錯的。此外,如果一端的SYN包到達對方的中間設備太快,那麼對方的中間設備就會拒絕SYN包並且發出RST包,致使本地的中間設備反過來關閉了新的會話且未來使用這個端口重傳SYN會失敗。最後,即使對“同時打開”的支持是TCP規範強制性的,在某些OS中也沒有正確的實現。出於這些原因,同樣這裏提到的這個小技術也是出於歷史的原因,應用程序不推薦使用。應用程序如果要求通過現有的NATs建立有效的,直接的P2P連接應該使用UDP。
 
 
 
 
4. 應用程序設計指南/Application design guidelines
 
 
 
4.1. 有中間設備該怎麼做/What works with P2P middleboxes
 
 
  由於UDP穿孔技術是爲在NATs後面的主機建立P2P連接的現存的最有效的方法,並且他使用於現在大多數的NATs,如果應用程序需要建立有效的P2P連接,推薦使用這個技術。但是,也要準備好不能建立P2P連接的時候可以使用中繼。
 
 
4.2. 雙方在同一個NAT後面/Peers behind the same NAT
 
 
  實際情況下,有很多的用戶不是有兩個IP地址,而是三個或者更多。這些情況下,很難或者根本不可能分辨出那一個地址發向了註冊服務器信息。這種情況下,應用程序應該送出他的所有地址(譯註:在Windows中,即使程序強制使用了MSG_DONTROUTE,winsock也會悄悄的忽略這個選項,並總是通過路由表決定發出數據的適當的接口《windows網絡編程技術》第一版 P210)。
 
 
4.3. 對端的發現/Peer discovery
 
  應用程序發包到許多地址來發現對一個特定的端來說哪一個是最佳的,這也許會在網絡上產生可觀的垃圾,當對端可能不適當的爲內網選用了一個可路由的地址(如11.0.1.1,他是爲DOD保留的)。因此,應用程序發出這種探測問候包時應當小心。
 
 
4.4. TCP P2P 應用程序
  應用程序開發人員廣泛使用的sockets API被設計用來開發C/S應用程序。在他的最初形式中,一個socket僅僅可以綁定一個TCP或者UDP端口。應用程序不能不允許有多個socket綁定同一個TCP or UDP端口,來同時發出和多個外部節點的會話,或者使用一個socket在一個端口上listen,其他socket發起向外的連接會話。
 
 
  然而,上面的這種single-socket-to-port綁定的限制對UDP不是問題,因爲UDP是基於數據報的協議。UDP程序設計者可以使用recvfrom()和sendto()調用來用一個socket發送和接收到多個客戶端的數據。
 
 
  對TCP而言,就行不通了。對TCP,輸入和輸出對應一個單獨的socket。Linux socket API用SO_REUSEADD選項來幫助解決這個問題。在FreeBSD和NetBSD上,這個選項不行;但可以用SetReuseAddress這個BSD函數(Linux沒有這個且不在Single Unix Standard中)。Win32 API也提供了一個等價的SetReuseAddress調用。使用上面提到的選項,應用程序可以使得一個TCP 端口供多個Socket重用。也就是說,打開2個TCP socket綁定到一個端口上,一個用來listen,另一個用來connect。
 
4.5. 使用midcom協議/Use of midcom protocol
 
 
  如果應用程序知道他要穿越的中間設備和實現這些中間設備的協議,應用程序就能夠使用midcom協議來簡化通過中間設備的過程。(譯註:這裏的midcom我想指的是NAT的端口映射規則、會話映射保留時間、incoming TCP packages 的處理等等)
 
 
  比如,P2P應用程序要求NAT中間設備保留端口綁定。如果中間設備支持midcom,P2P應用程序就可以控制端口綁定(或者地址綁定)參數,如存活時間,最大的idle時間,方向性---以使應用程序既可以連接又可以接收外部節點;不需要週期性的發送數據以使端口綁定存活。當應用程序不再需要綁定時,應用程序可以簡單的使用midcom協議的卸載命令。
 
 
5. NAT 設計指南/NAT Design Guidelines
 
 
 
   由於NAT影響P2P應用程序,本節討論他們的設計。
 
 
5.1. 不贊成使用對稱NATs/Deprecate the use of symmetric NATs
 
 
   對稱NATs隨着C/S應用程序如web瀏覽器而獲得普及,他僅需要發起向外的連接。然而,最近P2P應用程序如即時消息和音頻會議有着廣泛應用。對稱NATs不支持保留終端身份的特性也不適合P2P應用程序。爲了支持P2P應用程序,不贊成使用對稱NATs。
 
 
   P2P中間設備必須爲UDP通訊實現cone NAT的功能,允許通過UDP穿孔技術建立強健的P2P連接。理想情況下,P2P中間設備應該允許使用TCP和UDP建立P2P連接。
 
 
5.2. 爲對稱-NAT設備添加cone-NAT支持
 
 
   對稱NAT設備擴展支持P2P應用程序的一個方法是劃分可分配端口號的名字空間,保留一定比例的端口給one-to-one的會話和一些不同的端口給one-to-many會話。
 
 
   此外,一個NAT設備可被顯示的配置支持應用程序和主機所需要的P2P特性,以便NAT設備可自動的從合適的端口號碼塊中分配出P2P端口。
 
 
5.3. 爲UDP端口維護一致的端口綁定/Maintain consistent port bindings for UDP ports
 
 
   本篇文檔對NAT設計者的最基本和最重要的建議是,只要有一個活動的會話存在於給定的端口上,NAT就要爲給定的 (內部IP,內部PORT)和(外部IP,外部PORT)對維護一致的穩定的端口綁定。NAT可以檢查每一個輸入包的源、目的端口和地址過濾每一個輸入的會話通訊。當一個私有網絡中的節點發起一個向外的連接時,使用同一個源IP和UDP端口來解釋這個UDP會話,NAT應該確保當(某個內部主機)存在會話時,(這個內部主機的)新的UDP會話被指定在同一個公共IP和UDP端口號上。
 
 
5.3.1. 保留端口號/Preserving port numbers
 
 
   當建立新的UDP會話時,如果這個端口可用的話,有些NATs會嘗試分配和私有端口號(內網主機的端口)一致的公共端口(NAT上新分配的端口)。比如,A從內網10.0.0.1:1234發出一個向外的UDP會話,那麼NAT就會在自己分配端口時試圖使用1234這個端口。這項特性對一些想僅使用某個特定的UDP端口來會話的UDP應用程序而言會很有用,但是不推薦應用程序依賴這個特性,因爲僅當內網至多一個主機使用這個端口時,NAT纔會保留這個端口可用。
 
 
   此外,NAT不應該在一個新會話中保留端口,如果這樣做了,會和維護公共終端--私有終端地址綁定的一致性衝突。例如,假定內網主機A在端口1234和server S建立了會話,NAT A爲這個會話分配了62000端口,因爲此時NAT上的1234端口不可用。現在假定接下來NAT上1234端口可用了,而A和S的會話仍然是活動的,內網主機A又以1234端口初始一個和其他外部節點B的連接。這種情況下,由於端口綁定已經建立的是A的1234端口和NAT的62000的公網端口,這個端口綁定應該受維護,並且新的會話也應該使用62000端口作爲公網端口和內網主機A的1234端口一致。NAT不能僅僅因爲1234端口可用,就分配1234端口給這個新的會話:這個行爲不可能使得應用程序以任何方式獲益,因爲應用程序已經用一個已經分配的端口運行了,並且,他還會妨礙應用程序使用UDP穿孔技術和這個內網主機建立P2P連接的嘗試。
 
 
5.4. 維護TCP端口的一致性綁定/Maintaining consistent port bindings for TCP ports
 
 
   爲了和UDP解釋相一致,cone NAT實現者也應該爲TCP維護一致的(ip, port)在公網和私網的映射,就象上面描述的UDP的情況一樣。維護TCP終端端口綁定的一致性會增加NAT對P2P TCP應用程序的兼容性,這些應用程序從同一個源端口初始發起多個TCP連接。
  
5.5. P2P應用程序大的超時時間/Large timeout for P2P applications
 
 
   我們推薦中間設備實現者爲P2P應用程序使用最小的超時時間,比如5分鐘,配置綁定端口的idle-timeout。中間設備的實現者通常會使用更小的一個,就像他們現在做的。但是,更小的超時時間可能會有問題。考慮一下,一個P2P應用程序有16個對端。他每隔10秒發送激活包(keepalive packets)來避免NAT超時就會淹沒網絡。之所以這樣是因爲他會給中間設備發送5次激活包,以免激活包在網絡中丟失。
  
5.6. 支持迴路解釋/Support loopback translation
 
 
   我們強烈建議中間設備實現者支持迴路解釋功能,允許同一個中間設備後面的主機通過他們自己的公共的中間設備彼此通訊。在多級NAT的情況下,大容量的NATs被放置在第一級時,支持迴路解釋尤爲重要。象3.3.3節描述的那樣,在第一級NAT相同,但是第二級的NAT不相同時,除非第一級的NAT也支持迴路解釋,否則無法使用UDP穿孔技術彼此通訊,即使所有的中間設備保留終端的身份。
  
6. 安全考慮/Security Considerations
 
 
 
   本篇接下來的建議使得對應用程序或中間設備不會產生新的天生的安全問題。然而,如果這裏描述的技術沒有受到足夠的重視的話,新的安全風險也許會有。本節描述應用程序穿越中間設備建立P2P通訊時可能不經意的產生的安全問題和中間設備P2P友好時的隱式的安全策略。
 
 
6.1. IP地址別名/IP address aliasing
 
 
   P2P應用程序必須採用適當的授權機制來保護他們的P2P連接不受其他P2P連接的意外騷擾,也爲了防止惡意的攔截連接或者DOS(denial-of-service)攻擊。有效的NAT友好的P2P應用程序必須和多個不同IP地址域進行交互,但是一般不會注意到他們的確切拓撲或者這些地址域的管理策略。而通過UDP穿孔技術建立P2P通訊時,應用程序發出的包可能會經常到達整個網絡而不只是想要的那個主機。
 
 
   例如,多層NAT設備提供DHCP服務,默認配置爲分發給本地IP一個特定的地址範圍。比如,一個特定的NAT設備,默認情況,把192.168.1.100起始的地址分發。許多家庭私有使用NAT的網絡會有一個在那個地址上的主機,而這個地址也可能是192.168.1.101,如果一個主機A用UDP穿孔技術在一個私有網絡192.168.1.101中試圖和另一個私有網絡中的主機B 192.168.1.100建立P2P連接,那麼,作爲建立連接的過程的一部分,A會發送給192.168.1.100本地網絡一個尋找包,B也會給本地網絡發送一個到192.168.1.101的尋找包。顯然,這些尋找包不能到達想要的目的主機,因爲兩個主機在兩個不同的私網中,但是他們很可能到達各自網絡中使用這個標準UDP端口的應用程序中,造成潛在的混亂。尤其是如果這個應用程序也在其他的機器上運行且沒有適當的授權信息時。
 
 
   這個由於別名引起的風險,即使在沒有惡意攻擊的情況下也可能有。如果一個終端,比如A,確實是惡意的,那麼沒有適當授權的情況下,攻擊者就可以使得主機B以一種我們不期望的方式連接到和攻擊者(或者假想的攻擊者)同一個私網地址的其他主機。由於兩個終端主機A和B應該知道彼此是通過公網服務器S的,S和B都沒有辦法確認A給出的私有地址,所以,P2P應用程序必須認爲他們發現的任何IP地址都是可疑的,直到他們成功的建立了授權的雙向通訊。
 
 
6.2. DOS攻擊/Denial-of-service attacks
 
 
   P2P應用程序和支持該應用程序的公共servers必須保護自己不受DOS攻擊,並且確保他們不能被攻擊者用來安裝DOS攻擊其他目標。要保護他們自身,P2P應用程序和服務器必須在合法的雙向連接建立以前避免需要大量的本地處理或存儲資源。要避免被作爲一個DOS攻擊的工具,P2P應用程序和服務器在他們和預想的目標建立合法的P2P連接之前,必須最小化發送給新發現的目的IP的通信量的數量和速率。
 
 
   例如,註冊到公共server上的P2P應用程序可以告知自己的私有IP,或者多個IP地址。一個連接好的主機或者能夠吸引大量P2P連接的(例如,通過提供流行的內容服務)主機羣可安裝一個對目標主機C的DOS攻擊,僅僅通過在向服務器註冊時,把C的IP地址包含到自己的IP地址列表中就行了。服務器沒有辦法確認這些IP地址,因爲他們也可能是合法的用來建立本地網絡通訊的私有IP地址。
   P2P應用程序協議必須設計成對這些未經校驗的IP地址大小和速率受限的通訊,以避免導致這種集中效用帶來的潛在傷害。
 
 
6.3. 內部發起的攻擊/Man-in-the-middle attacks
 
 
   任何在P2P客戶端和集中服務器路徑之間的網絡設備,都可能安裝僞裝成NAT的各種man-in-the-middle攻擊。比如,假定A要向服務器註冊,但是一個正在監聽的攻擊者能夠觀察到這種註冊請求。攻擊者就可以通過發送和客戶請求一致的請求(除了修改源IP地址,比如改成攻擊者自己的)來淹沒服務器。如果攻擊者能夠說服服務器以攻擊者的身份註冊,那麼他就成爲未來這個通訊線路中代替原來客戶端的一個活動的組成部分了,即使攻擊者原來僅僅是嗅探到客戶到服務器的路徑。
 
 
   客戶端不能向服務器授權自己的源IP來保護他自己免受這種攻擊,因爲爲了成爲一個友好的NAT,應用程序必須允許NATs可以靜靜的修改源IP地址。這對NAT模型就出現了一個天生的安全缺陷。對這種攻擊唯一的防禦手段是用適當高的級別來鑑定和加密實際的   通信內容,這樣攻擊者就不能利用他的位置(譯註:指內網可以方便的監聽)。然而,即使所有應用層的通訊都被授權和加密處理,這種攻擊仍然可用通訊工具來分析客戶端正在和誰進行通訊。
 
 
6.4. 對中間設備安全的影響/Impact on middlebox security
   讓中間設備保留終端身份不會削弱中間設備的安全。比如,一個端口受限的cone NAT,在允許輸入和輸出通訊包通過中間設備的策略上,先天就不會比對稱NAT更加“混雜”(promiscuous)。只要向外的UDP會話可行,並且中間設備對內部和外部的UDP端口維護綁定的一致性,那麼,中間設備就可以過濾出從內部發起的不匹配的任何UDP輸入包。同樣,當維護端口綁定一致時,嚴格的過濾輸入包同樣使得中間設備是P2P友好的,而不會妥協拒絕不請自來包的原則。
 
 
   維護端口綁定一致性可導致對來自中間設備通訊的可預測性增加,這種預測性的增加是通過揭示不同UDP會話直接的關係,進而這個範圍裏面應用程序的行爲而獲得。這種可預測性對攻擊者在利用其他網絡或者應用程序級別的脆弱性可能很有用。然而,如果特殊情況下的安全要求非常的嚴格,要考慮的細緻入微,那麼,首先中間設備就不應該被配置成許可不嚴格的向外UDP通訊。這些中間設備應該僅僅允許從特定的應用程序在特定的端口,或者通過一個嚴格控制的應用層的網關進行通訊。這種情況下,就沒有希望穿過中間設備建立一般的、透明的P2P通訊(或者透明的c/s連接);中間設備要麼實現適當的具體應用程序的行爲,要麼整個就不允許通訊。
 
 
7. 致謝/Acknowledgments
 
 
   The authors wish to thank Henrik, Dave, and Christian Huitema for their valuable feedback.
 
 
8. References
 
 
8.1. Normative references
 [BIDIR]    Peer-to-Peer Working Group, NAT/Firewall Working Committee, "Bidirectional Peer-to-Peer Communication with Interposing Firewalls and NATs", August 2001. http://www.peer-to-peerwg.org/tech/nat/
 
 
[KEGEL] Dan Kegel, "NAT and Peer-to-Peer Networking", July 1999. http://www.alumni.caltech.edu/~dank/peer-nat.html
 
 
[MIDCOM]    P. Srisuresh, J. Kuthan, J. Rosenberg, A. Molitor, and A. Rayhan, "Middlebox communication architecture and framework", RFC 3303, August 2002.
 
 
[NAT-APPL]   D. Senie, "Network Address Translator (NAT)-Friendly Application Design Guidelines", RFC 3235, January 2002.
 
 
[NAT-PROT]   M. Holdrege and P. Srisuresh, "Protocol Complications with the IP Network Address Translator", RFC 3027,  January 2001.
 
 
[NAT-PT]     G. Tsirtsis and P. Srisuresh, "Network Address Translation - Protocol Translation (NAT-PT)", RFC 2766, February 2000.
 
 
[NAT-TERM] P. Srisuresh and M. Holdrege, "IP Network Address Translator (NAT) Terminology and Considerations", RFC 2663, August 1999.
 
 
[NAT-TRAD]  P. Srisuresh and K. Egevang, "Traditional IP Network Address Translator (Traditional NAT)", RFC 3022, January 2001.
 
 
[STUN]       J. Rosenberg, J. Weinberger, C. Huitema, and R. Mahy, "STUN - Simple Traversal of User Datagram Protocol (UDP) Through Network Address Translators (NATs)", RFC 3489, March 2003.
 
 
8.2. Informational references
 
 
[ICE]      J. Rosenberg, "Interactive Connectivity Establishment (ICE): A Methodology for Network Address Translator (NAT) Traversal for the Session Initiation Protocol (SIP)", draft-rosenberg-sipping-ice-00 (Work In Progress), February 2003.
 
 
[RSIP]     M. Borella, J. Lo, D. Grabelsky, and G. Montenegro, "Realm Specific IP: Framework", RFC 3102, October 2001.
 
 
[SOCKS]    M. Leech, M. Ganis, Y. Lee, R. Kuris, D. Koblas, and L. Jones, "SOCKS Protocol Version 5", RFC 1928, March 1996.
 
 
[SYM-STUN] Y. Takeda, "Symmetric NAT Traversal using STUN", draft-takeda-symmetric-nat-traversal-00.txt (Work In Progress), June 2003.
 [TCP]      "Transmission Control Protocol", RFC 793, September 1981.
 [TEREDO]   C. Huitema, "Teredo: Tunneling IPv6 over UDP through NATs", draft-ietf-ngtrans-shipworm-08.txt (Work In Progress), September 2002.
 
 
[TURN]     J. Rosenberg, J. Weinberger, R. Mahy, and C. Huitema, "Traversal Using Relay NAT (TURN)", draft-rosenberg-midcom-turn-01 (Work In Progress), March 2003.
 
 
[UPNP]     UPnP Forum, "Internet Gateway Device (IGD) Standardized Device Control Protocol V 1.0", November 2001. http://www.upnp.org/standardizeddcps/igd.asp
 
 
9. Author's Address
 
 
   Bryan Ford
   Laboratory for Computer Science
   Massachusetts Institute of Technology
   77 Massachusetts Ave.
   Cambridge, MA 02139
   Phone: (617) 253-5261
  E-mail: [email protected]
   Web: http://www.brynosaurus.com/
 
 
   Pyda Srisuresh
   Caymas Systems, Inc.
   11799-A North McDowell Blvd.
   Petaluma, CA 94954
   Phone: (707) 283-5063
   E-mail: [email protected]
 
 
   Dan Kegel
   Kegel.com
   901 S. Sycamore Ave.
   Los Angeles, CA 90036
   Phone: 323 931-6717   
   Email: [email protected]
   Web: http://www.kegel.com/
 
 
Full Copyright Statement
  
   Copyright (C) The Internet Society (2003). All Rights Reserved.
 
   This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way, such as by removing the copyright notice or references to the Internet Society or other Internet organizations, except as needed for the purpose of developing Internet standards in which case the procedures for copyrights defined in the Internet Standards process must be followed, or as required to translate it into languages other than English.
 
 
   The limited permissions granted above are perpetual and will not be revoked by the Internet Society or its successors or assigns.
 
 
   This document and the information contained herein is provided on an "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
 
 
------ < END > ------
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章