This is an archive of past FreeBSD releases; it's part of the FreeBSD Documentation Archive.

PPP

Chapter 10. PPP

Q: 我不能使用 ppp,我做錯了什麼嗎 ?
Q: 我一執行 ppp,它就掛在那邊不動了
Q: Ppp 在 -auto 模式下不能撥號
Q: 什麼叫做 "No route to host"
Q: 我的連線在三分鐘後自動斷掉了
Q: 我的連線因為負荷太重而斷線
Q: ppp 會不定時的斷線
Q: 連線會不定時當掉
Q: 在看到 Login OK! 的訊息以後就沒有反應了
Q: 我一直看到 magic being the same 的錯誤訊息
Q: LCP 的溝通一直到連線關閉才結束
Q: Ppp 在連線後就卡住了
Q: 用 shell 跳出 Ppp 做測試時,連線似乎卡住了
Q: 在 null-modem 線上建立的 Ppp 好像不會自動斷線
Q: 為什麼 ppp 在 -auto 模式下會無緣無故播號?
Q: 這些 CCP 錯誤訊息是指?
Q: 傳檔案時發生 IO 錯誤,然後 Ppp 就掛掉了
Q: 為什麼 ppp 不會記錄我的連線速度?
Q: Ppp 不理會 chat script 中的 `\' 字元
Q: Ppp 碰到了 seg-fault,但找不到 ppp.core 這個檔?
Q: 在 -auto 模式下,使 ppp 播號的程式在連線後卻連不到目的地
Q: 為何玩大多數遊戲時,都不能使用 -alias 這個參數?
Q: 那裡可以找到常用埠的列表?
Q: 什麼是 FCS 錯誤?
Q: 沒有一個方法可以用,我完蛋了啦!

Q: 我不能使用 ppp,我做錯了什麼嗎 ?

A: 你應該先看看 ppp man page 和 ppp 使用說明。使用以下指令來打開記錄 (logging) 的功能

        set log Phase Chat Connect Carrier lcp ipcp ccp command
      



這個命令可以在 ppp command prompt 或者是在 /etc/ppp/ppp.conf 組態檔案中加入。 (加在 default section 的開頭最好). 確定在 /etc/syslog.conf 裡面有這麼一行:

        !ppp
        *.*              /var/log/ppp.log
      



而且/var/log/ppp.log 這個檔案存在。 如此一來 你可以從 log 檔案中知道到底發生了什麼事情。 先不用擔心檔案的內容你看不懂,如果你要向人求救的話 ,救你的人會看得懂的。

如果你系統上的那份 ppp 不提供 "set log" 的指令的話,你應該去下載 最新版本。 這個版本在 FreeBSD 2.1.5 以上的版本都可以使用。

Q: 我一執行 ppp,它就掛在那邊不動了

A: 會發生這種情形通常是你的 hostname 沒有辦法解出來。解決這個問題 最好的辦法是確定 /etc/hosts 會被你的 resolver 第一個參考到。 你可以修改/etc/host.conf 並且把hosts 放到最前面。接著,只要把你的機器名稱放到 /etc/hosts 裡面就可以了。如果你沒有 local network 的話,修改 localhost 這一行:

127.0.0.1 foo.bar.com foo localhost
        



否則,就把你主機的資訊加入檔案中。你可以參考相關的 man pages 以獲得進一步的資訊。

如果你順利的完成這些動作,你應該可以成功的執行 ping -c1 `hostname` 。

Q: Ppp 在 -auto 模式下不能撥號

A: 首先確定你的內定路由 (default route) 是否有設定。下 netstat -rn 這個指令,你應該能夠看到如以下範例的兩個 entries:

Destination        Gateway            Flags     Refs     Use     Netif Expire
default            10.0.0.2           UGSc        0        0      tun0
10.0.0.2           10.0.0.1           UH          0        0      tun0
        



這些設定是假設您使用的 address 跟 handbook 裡面的、或是 man page 的範例、或者和 ppp.conf.sample 裡的設定相同。如果您沒有設定 default route,那麼有可能您現在使用舊版本的 ppp,舊的 ppp 會看不懂 ppp.conf 裡的 HISADDR。如果您的系統 ppp 是在 FreeBSD 2.2.5 之前的話,修改這一行

          add 0 0 HISADDR
        



成為

          add 0 0 10.0.0.2
        



default route 這行沒有出現的另一個原因是你設錯了 default router,這個設定在 /etc/rc.conf 檔案中(這個檔案在 release 2.2.2 前叫 /etc/sysconfig),你需要在 ppp.conf 中加入這 麼一行

          delete ALL
        



如果發生這種情形,回到 handbook userppp 最後設定 的說明中查詢。

Q: 什麼叫做 "No route to host"

A: 這個狀況通常是因為缺少了這段設定

          MYADDR:
            delete ALL
            add 0 0 HISADDR
        



請檢查您的 /etc/ppp/ppp.linkup 檔案中是否有這些設定。 只有在您使用動態 IP(dynamic IP) 或不知道您 gateway 的 IP 時才需要 設定這個。如果您是使用 interactive mode 的話,您可以在進入 packet mode 後輸入如下命令(如果 ppp 提示符號變成大寫的 PPP,便代表已 經進入 packet mode):

          delete ALL
          add 0 0 HISADDR
        



您可以參考 handbook 中 PPP 和動態 IP 位址 的部份,有較詳盡的說明。

Q: 我的連線在三分鐘後自動斷掉了

A: ppp 預設的 timeout 值是三分鐘。可以用以下這行命令調整

          set timeout NNN
        



這代表如果在 NNN 秒內網路都沒有動靜的話,ppp 就會自動關閉 連線。如果 NNN 設成 0,那麼將不會因為沒有資料來往而關閉連線。 你可以把這行命令放到 ppp.conf 這個檔案裡面,或是在 interactive mode 裡面輸入這個指令,也可以用 telnet 或 pppctl 連到 ppps 伺服器的 socket,在連線後隨時調整 timeout 的值。參考 ppp man page 以獲得更詳盡的資料.

Q: 我的連線因為負荷太重而斷線

A: 如果您設定要用 Link Quality Reporting(LQR),您和對方主機之間就 有可能遺失太多的 LQR 封包。Ppp 會因此判斷電話線路有問題,然後就會 切斷連線。在 FreeBSD 2.2.5 版以前,內定會使用 LQR,現在的內定值是 不用。LQR 可以用這一行命令取消

          disable lqr
        



Q: ppp 會不定時的斷線

A: 有時候如果線路上有太多雜訊,甚至如果您使用了電話插撥服務的話, 您的數據機將會掛斷電話,因為它誤認這些訊息是 lost carrier。

大部分的數據機都有容忍暫時失去 carrier 的設定。以 USR Sportster 為例,失去 carrier 和掛斷電話之間的時間,是以 1/10 秒為單位存在 S10 暫存器中。如果要讓您的數據機能容忍更長的時間,你可以在 dial string 裡面加入以下 "送出命令 - 等待字串" 的部份:

          set dial "...... ATS10=10 OK ......"
        



參考數據機內附的說明書以取得更詳細的資料。

Q: 連線會不定時當掉

A: 許多人的連線會毫無來由的卡住,首先要做的是找出連線那一方當掉。

如果用的是外接數據機,就用 ping 來看在傳資料時,TD 燈號 會不會閃。如果會的話(並且 RD 不會閃),代表是對方出問題;如果 不會,則是自己的問題。如果用內接數據機,先在 ppp.conf 中加入 set server 這道指令,當連線當掉時,執行 pppctl 連到 ppp。如果網 路連線突然好了(因為 ppp 看到用來診斷問題的 socket)或無法連上(假設 在一開始可以執行 set socket 這道指令),表示本地出問題。如果連 得上 ppp 卻仍然不能用,用 set log local async 打開本地的非同步 記錄,接著在另一個視窗(或終端機)執行 ping 在連線上傳送資料。 非同步記錄的功能會同時顯示送出和接收的資料,如果資料只出不進,就是對 方機器出問題。

知道是本地或對方出問題後,就有兩種可能:

Q: 對方的機器沒有回應

A: 在這方面能作的相當有限,大部份的 ISP 會因為你不是用 Microsoft 作業系統而不願幫忙。可以在 ppp.conf 中加入 enable lqr, 允許 ppp 偵測對方的錯誤而掛斷,但這個過程相當慢,所以不大實用。也 許不想告訴 ISP 你是用 user-ppp 上線的....

首先,用下面兩道命令關掉所有本地的壓縮功能:

            disable pred1 deflate deflate24 protocomp acfcomp shortseq vj
            deny pred1 deflate deflate24 protocomp acfcomp shortseq vj
          



然後重新連線,確定這樣不會有所不同。如果反而有進步或甚至將問題 解決掉,就用試誤法來找出是那個設定造成的。這樣在聯絡 ISP 時就可以 提供相當有用的資料(雖然會很容易看出你不是用 Microsoft 的產品)。

在聯絡 ISP 之前,打開本地的非同步記錄功能,接著就等連線再度當掉, 這可能會用到相當大的硬碟空間。最後從連接埠讀進的資料可能會相當有用, 它通常是 ASCII 文字,甚至有可能會說明問題出在那裡(``Memory fault, core dumped''?)。

如果 ISP 願意協助的話,應該會在他們那一端也打開記錄功能,那麼在 下次連線當掉時,就可以告訴你為何會出問題。很歡迎將詳細內容送到 brian@Awfulhak.org,甚至要 求 ISP 直接向我連絡。

Q: 自己的 Ppp 當掉了

A: 這裡能做的最多就是重新編譯 ppp:在 Makefile 最後面加上 CFLAGS+=-g 和 STRIP=,接著做 make clean && make && make install。在 ppp 當 掉時,先用 ps ajxww |fgrep ppp 找出 ppp 的 process id,然後執 行 gdb ppp PID。在 gdb 提示符號下,可以用 bt 找出 stack trace。

將結果送到 brian@Awfulhak.org.

Q: 在看到 Login OK! 的訊息以後就沒有反應了

A: 在 FreeBSD 2.2.5 以前的版本上,一旦連線建立完成以後, ppp 會等對方的機器啟動 Line Control Protocol (LCP)。很多 ISP 不會自動 啟動,而是等待由 client 端來啟動。要強迫 ppp 主動啟動 LCP,請 執行這個命令:

          set openmode active
        



Note: 通常如果兩邊都啟動訊息交換的話,通常不會造成任何副作 用,所以 openmode 目前內定是打開的。然而,下一段將解釋在什麼狀況下 這樣設定 真的 會造成副作用。

Q: 我一直看到 magic being the same 的錯誤訊息

A: 有時就在連上之後,在記錄檔會看到 "magic is the same" 的訊息。通 常這些是無害的,有時候某一端則會斷線。大多數的 ppp 實作無法解決這個 問題,就算似乎連上了,在記錄檔也可以看到一直重複的 configure request 和 configure acknowledgement 之類的溝通訊息,ppp 最後會放棄而關掉連 線。

會發生這種問題的通常情況是,伺服器用速度慢的硬碟、在通訊埠上執行 getty、並且等到使用者登入後才用 script 或程式執行 ppp;也有聽說用 slirp 就一定會發生類似問題的報告。原因是在 getty 結束和 ppp 開始執行 的這段時間內,client 端的 ppp 開始送出 Line Control Protocol(LCP) 封 包,由於伺服器通訊埠的 ECHO 仍在打開狀態,client 端的 ppp 就會看到送 出去的封包被 "反彈" 回來。

在用 LCP 溝通時,有部份是要連線兩邊分別建立自己的 magic number, 來偵測及避免封包被 "反彈" 回來的狀況。協定標準中說當對方試圖用和自己 相同的 magic number 溝通時,要送給對方一個 NAK 的訊號(表示不接受), 接著對方就會選另一個數字。但在伺服器通訊埠 ECHO 仍打開的這段期間, client 端的 ppp 送出 LCP 封包,看到相同的 magic number,於是送出 NAK 訊號。這個 NAK 也會被 "反彈" 回來,被誤認由對方送出,因此 client 端會改變自己的 magic number。這樣 magic number 的變動次數會非常地多, 並且也全都存在對方的終端機緩衝區中。當伺服器啟動 ppp 時,它馬上就 被 magic number 的大量更動所淹沒,並且(幾乎是立刻)決定已經試夠了 LCP 而放棄;在這期間,client 端雖然再也看不到被反彈的封包,但卻來得 及看到伺服器把電話線掛掉。

允許讓對方來作 LCP 溝通可以避免這種情形,在 ppp.conf 中加下面這 一行:

          set openmode passive
        



這行告訴 ppp 由對方來啟動 LCP,不過有些伺服器永遠都不會主動溝通 ,在這種情況下,可以這麼設定:

          set openmode active 3
        



這是要 ppp 等個三秒鐘,然後再開始送 LCP 相關要求。如果對方在這 段時間送出 LCP 封包,ppp 就不會等足三秒而立刻回應。

Q: LCP 的溝通一直到連線關閉才結束

A: 目前 ppp 在實作上有個會出問題的 "功能",不會將 LCP、CCP & IPCP 這幾種封包的回應和原先要求作對照。結果是如果有一方的 ppp 啟動時比對方慢了六秒以上,對方會在其間多送出兩個 LCP 的設定 要求,後果相當嚴重。

假設有兩端 A 和 B 都在執行 ppp,A 在連線後立刻 送出 LCP 要求,B 則花了七秒才開始,所以當 B 啟動時,A 早已送出三個 LCP REQ(request)。我們也假設連線已將 ECHO 關掉,否則就 會看到上個問題提到的 magic number 問題。B 啟動時也會送出 REQ, 同時對 A 送出的第一個 REQ 回應,送出 ACK(acknowledge)。A 收到這 個 ACK 後會進入 OPENED 狀態,同時也對 B 的第一個 REQ 送出 ACK。但在這段期間,B 會看到 A 之前多送出的兩個 REQ,因而也 以兩個 ACK 回應。B 接著看到 A 傳來的第一個 ACK,因此也進入 OPENED 狀態。但這時 A 收到 B 多送的兩個 ACK。根據 RFC 的規定,會對第二個 ACK 送出第四個 REQ 而回到 REQ-SENT 狀態 (再重複一次 REQ-ACK 的過程),但一看到第三個 ACK,A 以為是 B 回應剛剛送出的 REQ,又進入 OPENED 狀態。此時 B 收到 A 發出的第四個 REQ,根據 RFC,會對這個 REQ 送出 ACK,然後再送出 第二個 REQ(也是再重複一次 REQ-ACK 的過程)。A 收到這個 REQ 後 會再重新送 REQ 而回到 REQ-SENT 狀態,接著又收到 ACK 而進入 OPENED 狀態。因此雙方都會以為收到的 ACK 是對方回應剛剛送出去的 REQ,最後 A 會一直在 OPENED 和 REQ-SENT 兩種狀態間切 換,對 B 則是 OPENED 和 ACK-SENT。

這種惡性循環會一直持續著,直到有一方發現自己在原地打轉而放棄繼續 下去。

避免這種情況的最好方式,是將某一端設成被動模式-也就是等另一 方先開始溝通,用這道命令:

          set openmode passive
        



用這個選項時要小心,應該和這個命令一起用:

          set stopped N
        



這會設定 ppp 等待對方開始溝通的時間上限,另一個方法是用:

          set openmode active N
        



其中 N 是在主動溝通之前先等待的秒數,man page 有更詳細的說明。

Q: Ppp 在連線後就卡住了

A: 在 FreeBSD 2.2.5 之前的版本,有可能因為 ppp 在處理 Predictor1 壓縮時發生錯誤,使得在連線後馬上就卡住。只有當連線雙方都試圖用不同 種 Compression Control Protocol(CCP) 溝通時,才會發生這種情形。這個 問題已經解決了,但如果仍在用舊版的 ppp,可以用這種方法避免:

          disable pred1
        



Q: 用 shell 跳出 Ppp 做測試時,連線似乎卡住了

A: 在用 shell 或 ! 命令時,ppp 會執行 shell(ppp 也會把你指定的參數傳給 shell),Ppp 會等到這些命令結束後才繼續。如果 有使用到 ppp 連線的命令,連線會像是被凍住了,這是因為 ppp 正在 等這些指令結束。

如果想執行程式,用 !bg 這個命令,它會把程式丟到背景執行,ppp 接著就能繼續保持連線。

Q: 在 null-modem 線上建立的 Ppp 好像不會自動斷線

A: 由於 null-modem 本身用的線材,ppp 沒有辦法自動決定是否 某個直接連線已經斷掉。當使用這類方式的連線時,一定要打開 LQR:

          enable lqr
        



內定是會接受 LQR,如果對方用它來溝通的話。

Q: 為什麼 ppp 在 -auto 模式下會無緣無故播號?

A: 如果 ppp 非預期地播號,就必須要找出原因,然後設定播號過濾 器(dfilter, Dial filter)來避免這種情形。

要找出原因,先用這個命令:

          set log +tcp/ip
        



這樣會記錄經由連線的所有資料。下次如果又無故播號,就可以從記錄 旁邊的時間很快找到原因。

現在可以避免因為這些原因播號。通常是在作 DNS 查詢時才會發生這種 問題,要避免因 DNS 查詢而連線(這樣不會使 ppp 在連線狀態 下擋掉這些封包),用下面這幾行:

          set dfilter 1 deny udp src eq 53
          set dfilter 2 deny udp dst eq 53
          set dfilter 3 permit 0/0 0/0
        



這種做法並不永遠適用,因為它事實上使得你無法用 demand-dial 功能 - 大部份程式在做網路相關動作前都會用到 DNS 查詢。

在 DNS 這個情況下,應該試著找出到底是誰想要解出主機名稱,通常幾 乎都是由 sendmail 所造成,所以要在 sendmail 設定檔中指示它不要做任何 DNS 查詢。在 Mail 設定 一節中有詳細說明如何作出 自己的設定檔、及裡面應該放哪些設定,你也許想要將下一行加入 .mc 檔中:

          define(`confDELIVERY_MODE', `d')dnl
        



這會使 sendmail 先擋著所有信件,直到送信時再一齊送出去(通常 sendmail 執行時是用 ``-bd -q30m'' 這個參數,告訴它每三十分鐘才送信) 或是有人執行 ``sendmail -q''(也許可以放在 ppp.linkup 裡)。

Q: 這些 CCP 錯誤訊息是指?

A: 我在 log 檔一直看到這些錯誤訊息:

          CCP: CcpSendConfigReq
          CCP: Received Terminate Ack (1) state = Req-Sent (6)
        



這是因為 ppp 試圖作 Predictor1 壓縮方面的溝通,但對方的機器卻完 全不用壓縮功能。這些訊息是無害的,但如果不想看到它的話,可以把本地 ppp 的 Predictor1 壓縮也一起關掉:

          disable pred1
        



Q: 傳檔案時發生 IO 錯誤,然後 Ppp 就掛掉了

A: 在 FreeBSD 2.2.2 及先前的版本中,tun 的驅動程式有個問題,它不會 接收那些大過 tun 介面 MTU 的封包。如果收到比 MTU 大的封包,它會用 syslogd 記錄為 IO 錯誤。

但 ppp 規格中有提到,不管 LCP 溝通的結果如何,MRU 最小的可接受 值永遠是 1500。所以有可能你不小心將 MTU 調低於 1500,ISP 會不理它而送出 1500 大小的封包,然後就會觸發上述的 "功能"。

在 FreeBSD 2.2.2 及之前的版本中,永遠不要將 MTU 調低於 1500,就 可以解決這個問題。

Q: 為什麼 ppp 不會記錄我的連線速度?

A: 如果要記錄電腦和數據機間的每一行 ``對話'',用下一行打開:

          set log +connect
        



這會使 ppp 記錄所有資料,直到播號字串最後一個等待的數據機傳回值 為止。

如果使用 PAP 或 CHAP (因為沒有 "set login" 命令,所以設定檔中 CONNECT 之後就不會看到任何對話),想要看到連線速度的話,確定 ppp 等待的數據機傳回值是 CONNECT 這一整行,像這樣:

          set dial "ABORT BUSY ABORT NO\\sCARRIER TIMEOUT 4 \"\" ATZ OK-ATZ-OK ATDT\\T TIMEOUT 60 CONNECT \\c \\n"
        



這樣在看到 CONNECT 後不會送出任何東西,接著再等個換行字元,強 迫 ppp 讀取回應的 CONNECT 一整行。

Q: Ppp 不理會 chat script 中的 `\' 字元

A: Ppp 會去分析設定檔中的每一行,這樣它才會正確解讀像是 set phone "123 456 789" 的字串(你應該知道這個數字只是 <一個> 參數,如果要指定雙引號 (") 這個字元,必須在它前面用反斜線 (\)將它隔開)。

當解譯程式分析每個參數時,為了找出字串中所有像是 ``\P'' ``\T'' 的跳脫字元(見 man page),必須重新解譯該參數。在這種雙重分析之下, 你必須記得用正確的跳脫數目。

假設要對數據機送出 ``\'' 這個字元,應該像是:

          set dial "\"\" ATZ OK-ATZ-OK AT\\\\X OK"
        



這樣則會得到下面這串:

          ATZ
          OK
          AT\X
          OK
        



如果是

          set phone 1234567
          set dial "\"\" ATZ OK ATDT\\T"
        



則會得到下面結果:

          ATZ
          OK
          ATDT1234567
        



Q: Ppp 碰到了 seg-fault,但找不到 ppp.core 這個檔?

A: Ppp (或任何類似的程式) 應該不可能有 core dump。由於 ppp 執行時 的 effective user id 是 0 (即以 root 身份執行),作業系統在終止 ppp 前不會對磁碟寫它的 core 映像檔。如果 ppp 真的因為 segmentation violation 或其他一般會 core dump 的 signal 而終止、並且確定用 的是最新版本(見本節開頭),那麼你可以這麼做:

          $ tar xfz ppp-*.src.tar.gz
          $ cd ppp*/ppp
          $ echo STRIP= >>Makefile
          $ echo CFLAGS+=-g >>Makefile
          $ make clean all
          $ su
          # make install
          # chmod 555 /usr/sbin/ppp
        



你現在已經裝上可以用來除錯的 ppp 版本,由於權限上沒有作特別設定, 所以必須以 root 來執行 ppp,順便也要注意是在那個目錄執行的。

現在如果 ppp 碰到了 segmentation violation,就會將 coredump 存在 ppp.core 檔中,接下來就是:

          $ su
          # gdb /usr/sbin/ppp ppp.core
          (gdb) bt
          .....
          (gdb) f 0
          .....
          (gdb) i args
          .....
          (gdb) l
          .....
        



根據你的問題來取得相關資料,就可以診斷問題出在那裡。

如果熟悉 gdb,也許會想找出其他的詳細資料,像是那個動作造成 dump、及相關變數的位址及數值等。

Q: 在 -auto 模式下,使 ppp 播號的程式在連線後卻連不到目的地

A: 這是設定 ppp 在 -auto 模式向對方取得動態 IP 時的已知問題, 在最新版的 ppp 已經解決了 - 在 man page 中用 iface 關鍵字找找 看。

當用到網路的程式呼叫 connect(2) 時,socket endpoint 會設成 tun 這個界面的 IP,kernel 接著產生要送出 去的第一個封包,把它傳給 tun,Ppp 讀到這個封包後就會開始建立連 線。如果 ppp 用的是動態分配 IP,那麼就會改變 tun 界面的位址, 原先的 socket endpoint 就成為不正確的值。接著送到對方的封包通常都會 被丟掉,就算能順利達到對方機器,由於該來源 IP 已給其他人使用,任何回 應也不會被傳回本地的機器上。

理論上,有好幾種方法可以解決這個問題。如果 ISP 願意每次都提供相同 IP 當然是最好 :-),目前版本的 ppp 會做到這一點,但大多數的 ppp 實作不會這麼做。

從 client 端最容易的解決方式是,永遠都不要改變 tun 界面的 IP 值, 但是將所有出去的封包來源 IP 從原先的 tun 界面 IP 改為連線時取得的 IP,基本上這就是最新版 ppp 裡 iface-alias 選項的做法(使用 了 libalias(3) 和執行 ppp 時的 -alias 參數)-記住之前所有 用過的 tun 界面 IP,再把全部換成最近一次拿到的位址。

另一種方法(可能是最可靠)是寫個可以修改所有 socket endpoint 值的 system call。當拿到新的 IP 時,Ppp 就可以用它來修改所有執行程式 所建立的 socket。當 DHCP client 程式對 socket 重新使用 bind() 時,也 可以用同樣的呼叫。

還有一個可能則是允許不用 IP,就可以啟用某個網路界面。送出去的封包 來源 IP 會設成 255.255.255.255,直到 SIOCAIFADDR 這個 ioctl 第一次執 行完成為止。這樣會完全連結 socket 的兩端,而由 ppp 來修改來源的 IP 值,但只有當原來 IP 值是 255.255.255.255 時、或者 IP 值和 IP 偵錯 碼需要修改時才會去更動。這種方式有點算是 hack,即 kernel 可以對沒設 定好的界面送出壞掉的封包,因為假設會有其他機制可以修正這種錯誤。

Q: 為何玩大多數遊戲時,都不能使用 -alias 這個參數?

A: 遊戲或類似程式不能和 libalias 搭配使用的原因是,外面的機器試著對 著內部的機器開啟連線、或(不請自來地)送出 UDP 封包,而 alias 封包的 軟體不知道它應該把這些封包送到裡面的機器去。

解決的方式是,先確定現在只有執行那個會出問題的程式,然後在 gateway 機器上對 tun 界面執行 tcpdump、或在上面打開記錄 tcp/ip 的功 能(``set log +tcp/ip'')。

在啟動出問題的程式時,應該會在 gateway 機器上看到有封包通過,當外 界有傳回封包時則會被丟掉(這就是問題所在)。記下這些封包要送到目的地 的那個埠,然後關掉程式。重複幾次,看看是否都要送到同樣固定的埠,如果 是的話,在 /etc/ppp/ppp.conf 相關位置加上這一行,就可使程式正確運作:

          alias port proto internalmachine:port port
        



其中 ``proto'' 是 ``tcp'' 或 ``udp'',``internalmachine'' 是要接 收這些封包的機器,``port'' 則是這些封包要送到那個埠。

如果要在其他機器上執行同樣程式,必須重複同樣過程修改上一行設定, 否則就不能正常使用;也不可能在兩台內部機器上同時使用-畢竟外界只是把 這個內部網路看成一台機器而已。

如果封包不一定送到同樣的埠,你有三種選擇:

1) 在 libalias 加入對它的支援, /usr/src/lib/libalias/alias_*.c 有一些 ``特例'' 的示範(alias_ftp.c 是個不錯的原型檔)。通常是讀取某些可以認得出的外送封包,找出要外面連 到內部機器某個埠的指令,然後在 alias 表中設定 ``route'',以後再收到 這種封包就知道要往那裡送。

這是最困難的解法,但也是最好的,並且還可以在多台機器上用同樣程式。

2) 使用 proxy。舉例來說,該應用程式也許支援 socks5,或是 有個 ``passive'' 的選項(像是 ``cvsup'')可以避免對方向內部機器提出 連線的要求。

3) 用 ``alias addr'' 把所有資料都轉給內部機器,這是最後 才用的暴力法。

Q: 那裡可以找到常用埠的列表?

A: 現在還沒有,但可以將這些弄成一個名單(如果有人感興趣的話)。 在下面的例子裡,把 internal 換成玩遊戲那台機器的 IP。

  • Quake

    alias port udp internal:6112 6112

    如果想用其他方式,www.battle.net 有 Quake 對 proxy 支援的說明。



  • Quake 2

    alias port udp internal:27901 27910



  • 紅色警戒(Red Alert�

    alias port udp internal:8675 8675

    alias port udp internal:5009 5009



  • Half Life

    alias port udp internal:27005 27015



  • PCAnywhere 8.0

    alias port udp internal:5632 5632

    alias port tcp internal:5631 5631



Q: 什麼是 FCS 錯誤?

A: FCS 是 Frame Check Sequence 的縮寫。每一個 ppp 封包都附有偵錯碼來確定收到的資料的確是送出的資料。如果進來的某個 封包 FCS 不正確,就丟掉這個封包、再把 HDLC 裡的 FCS 計數器加 1。 用 show hdlc 便可看到 HDLC 裡的各種錯誤計數值。

不良線路(或封包被串列埠的驅動程式丟掉)有時候就會發生 FCS 錯誤, 雖然它的確會大大拖慢壓縮協定,不過通常這沒什麼大不了。如果你用的 是外接數據機,確定有保護線路不受外界干擾 - 這樣說不定就解決了。

如果在連上時馬上就凍住、並且還看到一大堆 FCS 錯誤的話,有可能 是因為你的連線並非是 8 bit clean。確定數據機不是用軟體流程控制 (XON/XOFF),如果你的連線 <一定> 要用軟體流程控制的話,用 set accmap 0x000a0000 這道命令告訴 ppp 跳過 ^Q 和 ^S 這兩個字元。

看到一大堆 FCS 錯誤的另一個原因,是連線另一端不再使用 PPP 溝通。這時候也許應該打開 async 的記錄功能,來決定是否進來的 資料其實是 login 或 shell 提示符號。如果另一端是 shell 提示符號, 先執行 close lcp、接著 term 就可以重新連接到對 方機器的 shell 下,而不用掛掉電話線。

如果記錄檔裡沒有任何資訊可以指示連線為何斷掉,那麼就該問問另一 端的管理員(你的 ISP?) 怎麼會這樣結束。

Q: 沒有一個方法可以用,我完蛋了啦!

A: 如果上面說的都沒用,就盡可能找出所有資訊,這包括了設定檔、如何 啟動 ppp、log 檔的相關部份、連線前後的 netstat -rn 輸出結果,把這些送到 freebsd-questions@FreeBSD.org mailing list 或 comp.unix.bsd.freebsd.misc newsgroup,這樣應該就會有人指點 正確的方向。