第10章 PPP

10.1. ppp が動きません。どこを間違えているのでしょう?
10.2. ppp を実行するとハングします
10.3. ppp が -auto モードでダイアルしてくれない
10.4. 「No route to host」 とはどういう意味ですか?
10.5. 3 分ほど経つと接続が切れてしまう
10.6. 負荷が高いと接続が切れてしまう
10.7. 接続がランダムに切れてしまう
10.8. 接続が不規則にハングアップしてしまう
10.9. 回線の向こう側での反応がない
10.10. ppp がハングアップする
10.11. Login OK! のメッセージが出た後、何も起こらない
10.12. でもまだ 「magic is the same」 というエラーが出る
10.13. 接続が切れるまで LCP のネゴシエーションが続くのですが。
10.14. ppp が接続直後に固まってしまう
10.15. ppp の内部でシェルを起動しようとすると固まってしまう
10.16. ヌルモデムケーブルを使用しているとき、 ppp が終了しない
10.17. ppp を -auto モードで動かすと、 勝手にダイアルすることがある
10.18. CCP エラーとはどういう意味ですか
10.19. ファイル転送の途中で、ppp が IO エラーを出して固まってしまう
10.20. どうして ppp は接続速度をログに残さないんでしょう?
10.21. 私の chat スクリプトでは 「\」 という文字を PPP が解釈してくれません。
10.22. ppp が segmentation fault になるのですが、 ppp.core ファイルがありません
10.23. auto モードでダイアルをするようなプロセスが接続されない。
10.24. 何故ほとんどのゲームが -nat スイッチ付きだと動かないんですか?
10.25. 有用なポート番号のリストはありませんか?
10.26. FCS エラーって何?
10.27. ゲートウェイで PPPoE を実行すると MacOS や Windows 98 との接続がフリーズしてしまうのですが、 これはなぜなのでしょうか?
10.28. どれにも当てはまらない! どうしたらいいの?

10.1.

ppp が動きません。どこを間違えているのでしょう?

まず ppp(8) のマニュアルと、 FreeBSD ハンドブックの「PPP」を読んでみましょう。 次に、

set log Phase Chat Connect Carrier lcp ipcp ccp command

という命令を ppp のコマンドプロンプトに対して打ち込むか、 設定ファイル /etc/ppp/ppp.conf に加えて (default セクションの先頭に加えるのが一番良いでしょう) ログを有効にしてみてください。 その際、 /etc/syslog.conf (syslog.conf(5) 参照) に

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

と書かれた行が含まれているか、また、 /var/log/ppp.log が存在しているかどうか確かめておいてください。 さて、これで何が起きているのか突き止めるために、 ログファイルからたくさんの情報を得られるようになりました。 ログに訳の分らない部分があっても心配ご無用。 あなたが助けを求めた誰かにとっては、 その部分が意味をなす場合があるのです。

訳注:

ログの取得に syslog を使用するようになったのは 2.2.5 以降からです。

使用中の ppp のバージョンで set log 命令を解釈しない場合は、最新版をダウンロードすべきです。 FreeBSD の 2.1.5 以降でビルドできます。

10.2.

ppp を実行するとハングします

ホスト名の解決がうまくいっていないのでしょう。まず、 リゾルバ (resolver) が /etc/hostsを参照するように、 /etc/host.conf の最初の行に host と書き込んでください。 つぎに、/etc/hosts に使用しているマシンのエントリを書き加えます。 ローカルでネットワークを使用していない場合は、 localhost の行を以下のように変更してください。

127.0.0.1      foo.bar.com foo localhost

使用しているホストのエントリを追加してもかまいません。 詳細は関連するマンページを参照してください。

10.3.

ppp-auto モードでダイアルしてくれない

まず最初に、デフォルトルートが確立しているかどうかチェックしてください。 netstat -rn (netstat(1) 参照) を実行すると、以下のような情報が表示されるはずです。

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

これはあなたがハンドブックやマニュアル、 ppp.conf.sample の中で出てくるアドレスを使用していると仮定した場合の例です。 デフォルトルートが確立していない場合、 ppp.conf の中の HISADDR が理解できない、 古いバージョンの ppp(8) が走っている可能性があります。 FreeBSD 2.2.5 より前のバージョンに付属していた ppp を使用している場合、

add 0 0 HISADDR

と書かれた行を以下のように修正してください。

add 0 0 10.0.0.2

netstat -rn でデフォルトルートの情報が表示されない場合、もう一つ、 /etc/rc.conf (rc.conf(5) 参照) (2.2.2 より前のリリースでは /etc/sysconfig と呼ばれていました) の中でデフォルトのルータを誤って設定し、 ppp.conf から

delete ALL

の行をうっかり消してしまった可能性があります。 この場合は、 FreeBSD ハンドブックの「システムの最終設定」の項を読み直してください。

10.4.

No route to host とはどういう意味ですか?

このエラーは通常、 /etc/ppp/ppp.linkup に以下のようなセクションが無い場合に起こります。

MYADDR:
  delete ALL
  add 0 0 HISADDR

これは動的 IP アドレスを使用している場合、 またはゲートウェイのアドレスを知らない場合にのみ必要な設定です。 インタラクティブモードを使用している場合、 パケットモードに入った後で (プロンプトが PPP と大文字に変わったらパケットモードに入ったしるしです)、 以下の命令を入力してください。

delete ALL
add 0 0 HISADDR

詳しい情報については、 FreeBSD ハンドブックの「PPP と動的 IP 設定」の項を参照してください。

10.5.

3 分ほど経つと接続が切れてしまう

ppp のタイムアウトは デフォルトでは 3 分です。 これは

set timeout NNN

という命令によって調整することができます。 NNN には、 接続が切れるまでのアイドル時間が秒数で入ります。 NNN が 0 の場合、 タイムアウトによる切断は起こりません。 このコマンドは ppp.conf に入れることも、 インタラクティブモードでプロンプトから入力することも できます。 ソケットを用いる telnet(1)pppctl(8) を使用し、 ppp サーバに接続することによって、 回線がアクティブな間に限定してタイムアウトの時間を調整することも可能です。

訳注:

pppctl は 2.2.5R からです。

詳しい情報は ppp(8) のマニュアルページを参照してください。

10.6.

負荷が高いと接続が切れてしまう

Link Quality Reporting (LQR) の設定を行っている場合、 マシンと接続先の間で非常にたくさんの LQR パケットが失われている可能性があります。結果として ppp は回線の具合いが悪いと考え、 回線を切断するのです。2.2.5 より前のバージョンの FreeBSD では LQR はデフォルトで有効になっています。 現在ではデフォルトの状態で無効です。 LQR は以下の命令で無効にすることができます。

disable lqr

10.7.

接続がランダムに切れてしまう

ノイズの多い回線、あるいは待ち機能付きの回線では、 時々モデムが (誤って) キャリアを失ったと思い込み、 回線が切断されてしまうことがあります。

大多数のモデムでは、 一時的なキャリアの喪失をどれくらいの時間で検出するかを、 設定で決めることができます。 たとえば USR Sportster では、S10 レジスタ の値を 10 倍した秒数がその値になります。 この場合、モデムをもっとのんびり屋さんにするには、 dial 行に次のような文字列を加えると良いでしょう。

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

詳しくはお使いのモデムのマニュアルをご覧ください。

10.8.

接続が不規則にハングアップしてしまう

たくさんの人が、原因不明のハングアップを経験しています。 検証のために必要なのは、まずどちら側のリンクでそれが起こっているか、 ということです。

外部接続型モデムを利用しているなら、 単に ping を使うことで、 データを送信するときに TD ランプが点灯するかどうかを確認することができます。 もし、TD ランプが点灯して、 RD ランプが点灯しなければ、 問題は回線の向こう側にあります。TD が点灯しなければ、 問題は回線のこちら側です。内蔵型モデムの場合、 ppp.conf ファイルに set server コマンドを入れる必要があるでしょう。 回線が切断されたとき、pppctl を使って ppp に接続してください。 そのとき、 ネットワーク接続が急に復旧 (診断ソケットへのアクセスで、 ppp が復活します) するか、 もしくは接続自体が全くできない (ただし、 ppp 起動時に set socket コマンドがちゃんと実行されているとします) としたら、 問題は回線のこちら側です。 もし、接続可能で、かつ状況が変化しなければ、 set log local async を使ってローカル非同期ログ (async logging) を有効にし、 ping を他のウィンドウかターミナルから使ってください。 非同期ログには、こちら側のリンクの送受信データが記録されます。 もし、データが送信されたにもかかわらず返って来ていなければ、 問題は回線の向こう側にあることになります。

問題が回線のどちら側かにあることが分かったら、 つぎの二つの可能性が考えられるでしょう。

10.9.

回線の向こう側での反応がない

これに対処できることはほとんどありません。大部分の ISP は、Microsoft 社製 OS 以外の利用者に対してのサポートを拒否するでしょう。 ppp.conf ファイルの中に enable lqr を記述することで ppp が回線の向こう側で発生する切断を検出することができますが、 この検出は比較的遅いため、あまり役に立ちません。また、あなたは user-ppp を利用していることを ISP に知られたくないと思うかも知れませんね。

まず最初に、こちら側の圧縮機能をすべて無効にしてみてください。 それには、設定ファイルをつぎのようにします。

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

そして再接続し、変更前と同じように通信できることを確認します。 もしこれによって状況が改善されるか、完全に解決したら、 (上の設定のうち) どの設定で状況が変化したのかを、 色々な組合せで試してみてください。これは、ISP に問い合わせを行なうときの有効な情報となります (ただし、 あなたが Microsoft 社製品以外のものを利用していることも明らかにしてしまいますが)。

ISP に問い合わせを行なう前に、こちら側の非同期ログを有効にして、 接続がハングアップするまで待ってください。この作業は、 非常に多くのディスク空間を消費するかも知れません。 興味の対象となっているのは、通信ポートから最後に読み込まれたデータです。 それは通常 ASCII データで、 問題点の詳細 (Memory fault, core dump など) が 記載されている可能性があります。

回線の向こう側で通信ログを監視することは可能なはずですので、 切断が発生した時、ISP の対応が好意的ならば どうして ISP 側で問題が発生したのかこちらに伝えてくれるかも知れません。 まで詳細を送って頂くか、ISP に直接私に連絡するように伝えて下さっても構いません。

10.10.

ppp がハングアップする

ベストな方法は、 CFLAGS+=-gSTRIP=pppMakefile に追加して、 ppp を再構築し、 そして make clean && make && make install を行なうことです。 ppp がハングアップした時、 ps ajxww | fgrep ppp を使って ppp のプロセス ID を調べ、 gdb ppp PID を実行してください。 gdb のプロンプトから、 bt を使ってスタックをトレースすることができます。

スタックトレースの結果は、 まで送ってください。

10.11.

Login OK! のメッセージが出た後、何も起こらない

2.2.5 より前のリリースの FreeBSD では、 ppp(8) はリンクが確立した後、接続先が Line Control Protocol (LCP) を発信するのを待ちます。しかし、多くの ISP ではネゴシエーションを自分からは起こさず、 クライアントが起こすのを待っています。 ppp に強制的に LCP を発信させるには、 次の命令を使います。

set openmode active

注記:

両方の側がネゴジェーションを起こしても、 大抵の場合は何の問題もありません。 ですから、現在では openmode はデフォルトで有効になっています。 次のセクションでこれが問題になる場合を説明します。

10.12.

でもまだ magic is the same というエラーが出る

時折、接続直後のログに magic is the same というメッセージがあらわれることがあります。 このメッセージがあらわれても何も起きない場合もありますし、 どちらかの側が接続を切ってしまう場合もあります。 ppp の実装の多くはこの問題に対応できておらず、 その場合にはちゃんと link が上がっている状態であっても、 ppp が最終的にあきらめてしまい、 接続を切るまで設定のリクエストが繰り返し送られ、 設定が行われたという通知がログファイルに残ると思います。

これは通常、 ディスクアクセスの遅いサーバマシンのシリアルポートで getty が生きていて、 ppp がログインスクリプトか、 ログイン直後に起動されたプログラムから実行されている場合に起こります。 slirp を使用している場合に同様の症状が見られたという報告もあります。 原因は getty の終了されるまでと、 ppp が実行され、 クライアント側の pppLine Control Protocol (LCP) を送り始めるまでのタイミングにあります。 サーバ側のシリアルポートで ECHO が有効なままになっているので、 クライアント側の ppp にパケットが「反射」してしまうのです。

LCP ネゴシエーションの一部として、 リンクの両サイドで magic number を定めて、 「反射」が起きていないかどうか確かめる作業があります。 規約では、接続相手がこちらと同じ magic number を提示してきたら、 NAK を送って新しい magic number を選択しなければならないと定めています。 この作業の間、サーバのシリアルポートの ECHO がずっと有効になったままなので、 クライアント側の pppLCP パケットを送り、 パケットが反射して全く同じ magic number が送られてくるのを見つけ、 それに対して NAK を送るのです。一方 NAK 自体も (これは ppp が magic number を変更しなければいけないことを意味しています) 反射してくるので、 結果として magic number が数えきれないほど変更され、 そのすべてがサーバの tty バッファの中に積み重なることになるのです。 サーバでスタートした ppp は、すぐに magic number であふれかえってしまい、 LCP のネゴシエーションを十分に行ったものと判断して、 さっさと接続を切ってしまいます。 一方、 クライアント側は反射が帰ってこなくなったので満足しますが、 それもサーバが接続を切ったことを知るまでです。

この事態は、以下の行を ppp.conf の中に書いて、 相手がネゴシエーションを開始できるようにする事によって回避できます。

set openmode passive

これで ppp はサーバが LCP ネゴシエーションを起こすのを待つようになります。 しかし、 自分からは決してネゴジェーションを起こさないサーバもあるかもしれません。 もしこの状況に遭遇した場合には、次のようにしてください。

set openmode active 3

これによって ppp は 3 秒間 passive モードを続けた後で、 LCP リクエストを送り始めます。 この間に相手がリクエストを送り始めた場合には 3 秒間待たずにこのリクエストに即座に応答します。

10.13.

接続が切れるまで LCP のネゴシエーションが続くのですが。

現在の ppp は、まだ LCPCCPIPCP の返事が、 元のリクエストと連携してくれる機能がきちんと実装されていません。 その結果、ある ppp の実装が相手よりも 6 秒以上遅い場合には、 LCP 設定のリクエストをさらに 2 回送ります。 これは致命的な物です。

ABという 2 つの実装を考えてみましょう。 A が接続の直後に LCP リクエストを送り、 一方 B の方はスタートするのに 7 秒かかったとします。B がスタートする時には ALCP リクエストを 3 回送ってしまっています。 前の節で述べた magic number の問題が起きないよう、 ECHOoff になっていると考えています。 BREQ を送ります。 するとこれは AREQ のうち、 最初の物に対する ACK となります。 結果として、AOPENED の状態に入り、 B に対して (最初の) ACK を送ります。 そのうちに B は、B がスタートする前に A から送られたもう 2 つの REQ に対する ACK を送り返します。 BA からの最初の ACK を受け取り OPENED の状態に入ります。 AB からの 2 つ目の ACK を受け取りますので、 REQ-SENTの状態に戻り、 さらに、RFC のとおりに (4 つ目の) REQ を送ります。そして 3 つ目の ACK を受け取って OPENED 状態に入ります。 一方、BA からの 4 つ目の REQ を受け取りますので、 ACK-SENT の状態に入り、2 つ目の REQ と 4 つ目の ACK を RFC のとおりに送ります。 Aは、 REQ を受けとると REQ-SENT の状態になり、さらに REQ を送ります。 そしてすぐに ACK を受け取って OPENED の状態に入ります。

これが、片方の ppp があきらめてしまうまで続きます。

これを回避する最も良い方法は、 片方を passive モードに設定する、 すなわち反対側がネゴシエーションを開始するまで待つようにする事です。 これは、

set openmode passive

というコマンドでできます。 このオプションは気を付けて使わないといけません。さらに

set stopped N

というコマンドを追加して、 ppp がネゴシエーションが開始するまで待つ 最大の時間を設定してください。もしくは、

set openmode active N

というコマンド (ここで、 N はネゴシエーションが始まるまで待つ時間) を使うこともできます。 詳しくはマニュアルページを参照してください。

10.14.

ppp が接続直後に固まってしまう

2.2.5 より前のバージョンの FreeBSD では、ppp が Predictor1 圧縮のネゴシエーションを誤って解釈して、 接続直後にリンクを無効にしている可能性があります。 これは両サイドが異なる Compression Control Protocols (CCP) を使ってネゴジェーションを行った場合にのみ発生します。 この問題は現在は解決していますが、あなたの走らせている ppp のバージョンが古い場合でも、次の命令で解決することができます。

disable pred1

10.15.

ppp の内部でシェルを起動しようとすると固まってしまう

shell あるいは ! コマンドを使用すると、 ppp はシェルを起動し (何か引数を渡した場合は、 ppp は引数も実行します)、 コマンドが終了するまで処理を中断します。 コマンドを実行中に ppp のリンクを使おうとすると、 リンクが固まっているように見えますが、 これは ppp がコマンドの終了を待っているからです。

このような場合は、代わりに !bg コマンドを使用してください。 与えられたコマンドがバックグラウンドで実行されるので、 ppp はリンクに関するサービスを継続することができます。

10.16.

ヌルモデムケーブルを使用しているとき、 ppp が終了しない

ヌルモデムケーブルを使用して直接接続している場合、 ppp は自動的には接続の終了を知ることができません。 これはヌルモデムシリアルケーブルの配線に起因しています。 この種の接続形態を用いる場合は、 以下の命令を用いて LQR を常に有効にする必要があります。

enable lqr

こうすると、接続先がネゴシエーションを行う場合、デフォルトで LQR の使用を受け入れるようになります。

10.17.

ppp-auto モードで動かすと、 勝手にダイアルすることがある

ppp が思いもしないときにダイアルを始める場合、その原因を突き止め、 防止のためにダイヤルフィルタ (dfilters) をかけてやる 必要があります。

原因を突き止めるためには、以下の命令を使用してください。

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

これはデマンドダイヤル機能に問題を生じさせるため、 常に適切であるとはかぎりません。 ほとんどのプログラムは他のネットワーク関連の処理を行なう前に DNS への問い合わせが必要になります。

DNS の場合は、 何が実際にホスト名を検索しようとしているのかを突き止めるべきでしょう。 大抵の場合は、 sendmail(8) が犯人です。 設定ファイルで sendmail が DNS に問い合わせないようになっているか確認すべきです。 自分用の設定ファイルを作成するための詳しい方法は、 メールの設定 の項をご覧ください。 または、 .mc ファイルに次のような行を追加してもよいでしょう。

define(`confDELIVERY_MODE', `d')dnl

この行を追加すると、sendmail はメールキューを処理する (通常 sendmail は 30 分ごとにキューを処理するよう、 -bd -q30m というオプションを付けて起動されます) までか、 または (多分 ppp.linkup というファイルの中で) sendmail -q というコマンドが実行されるまで、 すべてのメールをキューに溜めるようになります。

訳注:

sendmail -q はその時点のメールキューの内容を処理して終了します。

10.18.

CCP エラーとはどういう意味ですか

ログファイル中の以下のエラーは、

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

のネゴシエーションにおいて ppp は Predictor1 圧縮を用いるべく主張したのに対して、 接続先は圧縮を使用しないことを主張した場合に起こります。 このメッセージには何の害もありませんが、 出るのが嫌なら、以下の命令を用いてこちら側でも Predictor1 圧縮を無効にすることで対応できます。

disable pred1

10.19.

ファイル転送の途中で、ppp が IO エラーを出して固まってしまう

FreeBSD 2.2.2 以前のバージョンの tun ドライバには、tun インタフェースの MTU のサイズより大きなパケットを受け取ることができないというバグがありました。 MTU のサイズより大きなパケットを受け付けると IO エラーが起こり、 syslogd 経由で記録されるのです。

ppp の仕様では、 LCP のネゴシエーションを行う場合を含むどのような場合でも最低 1500 オクテットの Maximum Receive Unit (MRU) を受け入れる必要があります。 ですから、MTU を 1500 以下に設定した場合でも、ISP はそれに関係なく 1500 の大きさのパケットを送ってくるでしょう。 そしてこのイケてない機能にぶちあたって、 リンクが固まるのを目にすることになるのです。

FreeBSD 2.2.2 以前のバージョンでは、MTU を決して 1500 より小さくしないことで、 この問題を回避することができます。

10.20.

どうして ppp は接続速度をログに残さないんでしょう?

モデムとの「やり取り」すべての行をログに残すには、 以下のようにして接続速度のログの有効化を行ってください。

set log +connect

これは ppp(8) に最後にくることが要求されている expect という文字列がくるまでのすべてのものをログに記録させます。

接続速度はログにとりたいけれど、PAPCHAP を使っている (その結果、ダイヤルスクリプト中の CONNECT 以降に全く「やりとり」を行わない - set login スクリプトには何も書かない) のであれば、 pppexpect を含んだ CONNECT 行すべてがくるまで待たせるようにしないといけません、 以下のようになります。

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

ここで、CONNECT を受信してから、 何も送らず、復帰改行 (linefeed) を待っています、 pppCONNECT の応答すべてを読み込ませているわけです。

10.21.

私の chat スクリプトでは \ という文字を PPP が解釈してくれません。

PPP は設定ファイルを読み込むときに、 set phone "123 456 789" のような文字列を正しく解釈し、 番号が実際に1 つの引数であると理解します。 " という文字を指定するには、バックスラッシュ (backslash; \) でエスケープしなければなりません。

chat の各引数が解釈されるときには、 \P\T のような特別なエスケープシーケンス (マニュアルページ参照のこと) を見付けるために、 もう 1 回、字句解析を行います。 このように字句解析は 2 回繰り返されますので、 正しい回数だけエスケープ処理を行わないといけません。

モデムにたとえば \ のような文字を送りたい場合には、 次のようにする必要があります。

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

10.22.

pppsegmentation fault になるのですが、 ppp.core ファイルがありません

ppp (や他のプログラム) は決して core を吐いてはいけません。 ppp は実効 uid が 0 で動いていますので、 オペレーティングシステムは ppp を終了させる前にディスクに core イメージを書き込みません。 しかし ppp は実際にはセグメンテーション違反や、 他の core を吐く原因となるようなシグナルによって終了しており、 さらに最新のバージョン (このセクションの始めを見てください) を使用しているならば、次のようにしてください。

% 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 がインストールされます。 rootppp を実行し、 すべての特権が無効になっているようにする必要があるでしょう。 ppp を実行する時には、 カレントディレクトリが make したディレクトリであるようにしてください。

これで、ppp がセグメンテーション例外を受け取ったときには ppp.core という名前の core ファイルを吐くようになります。core が 吐かれたら次のようにしてください。

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

質問する際には、これらすべての情報を提供して、 問題点の分析ができるようにしてください。

gdb の使い方に慣れている場合には、実際に dump の原因となった理由やそのアドレス、 関連した変数の値なども調べる事ができるでしょう。

10.23.

auto モードでダイアルをするようなプロセスが接続されない。

これは ppp がローカル側の IP アドレスを、 動的に通信相手と交渉するように設定されている時に発生する良く知られた障害でした。 最新のバージョンでは、 この問題は修正されています。 iface をマニュアルページから検索してみてください。

これは、最初のプログラムが connect(2) を呼び出した時、tun インターフェイスの IP アドレスが、 ソケットの終端に割り当てられてしまうという問題です。 カーネルは、 外へ出ていく最初のパケットを作り、それを tun デバイスへ書き込みます。 そして ppp は、 そのパケットを読み込んで接続を確立します。 ppp は動的に IP アドレスを割り当てるため、 もしインターフェイスのアドレスが変化してしまうと、 最初に割り当てられたソケット終端の IP アドレスは無効になってしまいます。 そのため、それ以降相手に送られるすべてのパケットは通常、 相手に届くことはないでしょう。もし仮に届いたとしても、 既にこちらの IP アドレスは変更されているので、 どんな反応も最初のマシンには戻ってきません。

この問題に対処する理論的な方法がいくつかあります。もし可能なら、 相手が再度、同じ IP アドレスを割り当ててくれることが一番です :-) ppp の現在のバージョンはこれを行ないますが、 他のほとんどの実装はそういった動作をしません。

我々の側から対処できる最も簡単な方法は、tun インターフェイスの IP アドレスを固定する事です。またそのかわりに、 外に出ていくパケットを変更して、 発信元 IP アドレスをインターフェイスの IP アドレスから、交渉によって得られた IP アドレスに、 適宜書きかえる事によっても対処できます。 これは、基本的に ppp の最新バージョンにある iface-alias オプションが行なっていることと同じです (libalias(3) および、ppp-nat スイッチにも関係します)。それは、以前の IP アドレスをすべて管理し、 それらを最後の交渉によって得られた IP アドレスに対して NAT 機能を有効化します。

もう 1 つの (おそらく最も信頼できる) 方法は、bind された すべてのソケットの IP アドレスを、 異なるものに変更できるシステムコールを実装することです。 pppは、 新しい IP アドレスが割り当てられた時、 このシステムコールを用いて実行されているプログラムにある、 すべてのソケットを書きかえてやるわけです。 同じシステムコールが、DHCP クライアントが利用するソケットを 強制的に再 bind するのにも使うことができるでしょう。

3 つ目の方法は、IP アドレスを指定しないでインターフェイスを利用できるようにすることです。 外に出ていくパケットは、最初の SIOCAIFADDR ioctl の完了まで、 255.255.255.255 という IP アドレスが与えられます。 これによって、ソケットは常に bind することができます。 発信元 IP アドレスを変更するのは ppp の仕事です。ただし、 それは発信元 IP アドレスが 255.255.255.255 になっていて、IP アドレスと IP チェックサムを変更する必要がある場合だけです。 これは、カーネルが不適切に設定されたインターフェイスへは 異常なパケットを送出しようとすることを利用して、なにか他の 仕組みが遡及的に修正を行ってくれることを前提にしている、 割り切った方法ではあります。

10.24.

何故ほとんどのゲームが -nat スイッチ付きだと動かないんですか?

libalias を使っている時にゲームなどの類のものが動作しない理由は、 外側にあるマシンが接続しようとしているか、内側にあるマシンに (余計な) UDP パケットを送信しようとしているからです。 内側のマシンにこれらのパケットを送るべきかについて、 NAT ソフトウェアは関知しません。

うまく動かすためには、 実行中のものが問題の発生しているソフトウェアだけであるかを確認し、 ゲートウェイの tun インタフェースに対して tcpdump を実行するか、 ゲートウェイ上で pppTCP/IP ログ記録を有効化 (set log +tcp/ip) してください。

行儀の悪いソフトウェアを起動する際に、 ゲートウェイマシンを通過するパケットを監視すべきです。 外側から何かパケットが戻ってきた時に、 そのパケットは破棄されるでしょう (それが問題なのです)。 これらのパケットのポート番号に注意して、 その行儀の悪いソフトウェアを停止してください。 これを数回繰り返してポート番号が常に同じであるかを確認してみてください。 同じであった場合は、 /etc/ppp/ppp.conf の適切なセクションに次の行を入れると、 そのソフトウェアは動作するようになるでしょう。

nat port proto internalmachine:port port

ここで prototcpudp であり、 internalmachine はパケットを送りたいマシン、そして port はパケットの送信先のポート番号です。

上記のコマンドを変更せずに、 他のマシン上でそのソフトウェアを使用できるようにはしたくないかもしれません。 そして同時に二つの内部のマシン上でそのソフトウェアを実行することは、 この質問の範囲を超えています。結局、外側の世界からは、 内部ネットワーク全体がただ一つのマシンとして見えるのです。

ポート番号が常に同じとは限らない場合、さらに三つのオプションがあります。

  1. libalias でサポートするようにし、結果を送り付ける。 特定の場合の例は /usr/src/lib/libalias/alias_*.c にあります (alias_ftp.c は良いプロトタイプです)。これには通常、外向きの特定のパケットを読み、 内部の計算機のある特定のポートへの接続を開始するような命令が、 外部の計算機対して送られていることを見分け、 後続のパケットがどこに行けばいいのかが分かるように、 エイリアステーブル中の route の部分を設定する、という作業が含まれます。

    これは最も難しい方法ですが、最も良い方法でもありますし、ソフトウェアが 複数の計算機で動くようにできます。

  2. プロキシ (proxy) を使う。アプリケーションが、たとえば socks5 をサポートしているか、(cvsup のように) passive オプションを持っているとこの方法が使えます。 passive とは相手側のほうから接続を求めてくることを避けるためにあるオプションです。

  3. nat addr を使ってなんでもかんでも内部の計算機に向けて流してしまう。 これはちょっと無理矢理な解決法です。

10.25.

有用なポート番号のリストはありませんか?

まだ出来ていません。しかし、 これは (関心を持って頂けるならば) そういったリストにしていく予定です。 それぞれの例にある internal は、 ゲームで遊ぶマシンの IP アドレスに置き換えてください。

Asheron's Call
nat port udp internal:65000 65000

手動でゲームのポート番号を 65000 に変更してください。 マシンが複数ある場合は、それぞれのマシンに重複しないポート番号 (つまり 65001、65002 など) を設定し、その設定ごとに nat port の行を追加します。

Half Life
nat port udp internal:27005 27015
PCAnywhere 8.0
nat port udp internal:5632 5632
nat port tcp internal:5631 5631
Quake
nat port udp internal:6112 6112

このように設定する代わりに、 www.battle.net で Quake のプロキシ (proxy) がサポートされているか調べてもいいでしょう。

Quake2
alias port udp internal:27901 27910
Red Alert
nat port udp internal:8675 8675
nat port udp internal:5009 5009

10.26.

FCS エラーって何?

FCS とは Frame Check Sequence (フレームチェックシーケンス) の略です。 個々の ppp パケットには、 送受信するデータが正しいかを調べるためのチェックサムが含まれています。 受信したパケットの FCS が正しくない場合は、そのパケットは廃棄され、 HDLC FCS カウントが増やされます。 HDLC エラーの数は、 show hdlc コマンドを使って表示できます。

リンクの品質が悪かったり、 シリアルドライバがパケットを取りこぼしていたりすると、 FCS エラーがたびたび発生します。 FCS エラーは、 圧縮プロトコルの速度低下の原因にはなりますが、 特に心配する必要はありません。 外付けモデムを使っている場合は、 ケーブルがちゃんとシールドされているかを確認してください。 そうでない場合、 FCS エラーの原因となる場合があります。

接続直後からリンクがフリーズし、大量の FCS エラーが発生する場合は、 リンクが 8 ビットクリーンでない可能性があります。 ソフトウェアフロー制御 (XON/XOFF) が使われていないことを確認してください。 どうしてもソフトウェアフロー制御を使わなければならない場合は、 set accmap 0x000a0000 コマンドを使用して、 ppp^Q^S をエスケープさせてください。

リモートホストが PPP プロトコルを使用してない場合も、大量の FCS エラーが発生します。 この場合はログをとりながら非同期で接続し、 ログインプロンプトやシェルプロンプトが送られて来ていないか確認してください。

ログファイルにリンクを終了した原因となるような記録がない場合は、 リモートホスト (プロバイダ?) の管理者に、 セッションを終了された理由を尋ねてください。

10.27.

ゲートウェイで PPPoE を実行すると MacOS や Windows 98 との接続がフリーズしてしまうのですが、 これはなぜなのでしょうか?

Michael Wozniak 氏が、この現象に関して説明してくれました。 また、Dan Flemming 氏は MacOS での解決策を提供してくれました。 情報の提供に感謝します。

これは、いわゆる「ブラックホールルータ (Black Hole router)」に原因があります。 Windows 98 と MacOS (および、おそらく他の Microsoft 社製 OS) の TCP パケット送出は、 PPPoE のフレーム (Ethernet の MTU は標準で 1500) に入らないような大きなセグメントサイズを要求します。 そしてさらに分割禁止 (don't fragment) フラグビットを (TCP パケットにデフォルトで) セットするのですが、 Telco のルータは、分割が必須 ("must fragment") であることを示す ICMP メッセージを、接続しようとするウェブサイトに対して送出しません (つまり、ルータは正しく ICMP パケットを送出しているのですが、 ウェブサイトのファイアウォールがそれを落としているのです)。 そのためウェブサーバが PPPoE 接続に対して大きすぎるフレームを送出すると Telco のルータはそのフレームを捨ててしまい、 見ようとしたページが表示されないという症状が現われます (MSS より小さいページや画像は表示されます)。 ほとんどの Telco PPPoE 設定は、標準でこのように設定されているようです。 (ああ、彼らがルーティングプログラムの作り方を理解してさえいれば…)。

一つの解決法は、Windows 95/98 マシンで regedit を使い、 次のレジストリエントリを追加することです。

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Class\NetTrans\0000\MaxMTU

レジストリエントリは、1450 の値 (もっと正確に言うと、TCP パケットを PPPoE フレームに完全に適合させるには 1464 であるべきでですが、 1450 とすると、現われる可能性がある他の IP プロトコルに対してエラーマージンを確保することができます) にする必要があります。 このレジストリキーは、Windows2000 で Tcpip\Parameters\Interfaces\ID for adapter\MTU に移されたという報告がありました。

FreeBSD/NAT/PPPoE ルータと共存させるために Windoze の MTU を変更する方法に関する詳細は、 Microsoft Knowledge Base にある、 番号 Q158474 - Windows TCPIP Registry Entries、 および番号 Q120642 - TCPIP & NBT Configuration Parameters for Windows NT を参照してください。

残念なことに、MacOS には TCP/IP 設定を変更する方法がありません。 しかし、Sustainable Softworks 社 が販売している OTAdvancedTuner (OT は OpenTransport という MacOS の TCP/IP スタックの名前のこと) のような商用ソフトウェアが存在します。 このソフトウェアは、ユーザから TCP/IP 設定の変更を行なうことを可能にします。 MacOS NAT ユーザはドロップダウンメニューから ip_interface_MTU を選択し、 ボックスにある 1500 の代わりに 1450 を入力し、 Save as Auto Configure の隣のボックスをクリックして Make Active をクリックする必要があります。

ppp の最新版 (2.3 かそれ以降) には、自動的に MSS を適切な値に調節する enable tcpmssfixup コマンドがあります。 この機能は標準で有効になっています。 もし旧バージョンの ppp を使わなければならない状況にあるなら、 tcpmssd の port をご覧になると良いでしょう。

10.28.

どれにも当てはまらない! どうしたらいいの?

これまでのすべての質問に当てはまらない場合、設定ファイル、 ppp の実行方法、ログファイルの該当部分と netstat -rn コマンドの出力 (接続前と接続後) を含む、 あなたの持っているすべての情報を FreeBSD general questions メーリングリストcomp.unix.bsd.freebsd.misc ニュースグループへ送ってください。誰かがあなたを正しい方向へ導いてくれるでしょう。

本文書、および他の文書は ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/ からダウンロードできます。

FreeBSD に関する質問がある場合には、 ドキュメント を読んだ上で <questions@FreeBSD.org> まで (英語で) 連絡してください。

本文書に関する質問については、 <doc@FreeBSD.org> まで電子メールを (英語で) 送ってください。