双六工場日誌

平凡な日常を淡々と綴ります。

no_proxy にネットワークアドレスとかワイルドカードを指定しても期待通りに動かない、でどうするかというお話

世の中には、イントラなど直接インターネットに繋ぐことができず、プロキシ経由でしかインターネットに出られない環境で、検証をやっている人も多いと思います。 僕自身もそういうことが多く、検証環境を作り直す度にプロキシ設定不備で無駄にハマったりと時間をとられることが度々ありました。

それで、この際、ちゃんとまとめておくかと思ってブログを書き始めたのですが、ぐぐってみると全く同じような問題意識で書かれたブログ記事があって、全般的な内容はそちらに書かれていたので、落ち穂拾い的に no_proxy の設定だけ補足を書いてみます。

プロキシ設定についての全般的な内容が書かれているブログはこちら。

上記のブログでは、見落としがちで面倒なsudoの設定や、gitの設定まで網羅されているので、大概のプロキシ設定はこの内容で何とかなると思います。*1

ということで、プロキシ設定全般の話は、そちらを参照してもらえばよくなったので、落ち穂拾いとして、こちらには書かれていない no_proxy のハマりどころだけ取り上げたいと思います。

Linuxで、プロキシを設定するのに一番簡単な方法は、以下のように環境変数でプロキシ設定をする方法です。これを設定していると多くのプログラムで、指定されたプロキシを使うようになっています。

export http_proxy=http://proxy.example.com:8080/
export https_proxy=http://proxy.example.com:8080/

ただ、この方法だとそのシェルから実行されるプログラムでのHTTP(S)アクセスがすべてプロキシ経由となってしまうため、検証環境内部で動いているサービスへのアクセスにもプロキシを使おうとしてしまいます。 それを避けるために設定するのが「no_proxy」環境変数です。たとえば、以下のように設定します。

export no_proxy=127.0.0.1,localhost,192.168.1.1

たとえば、ログインシェルからクライアント起動して検証環境内部のコンポーネントに直接HTTP通信を行い、同時に、最新のソースコードやパッケージはプロキシを通じて外部から取得したい場合*2には、このように「no_proxy」まで設定してやる必要があります。

ここまでは上記のブログにも書かれている内容です。

ただ、この際の「no_proxy」の仕様が曲者で、僕が確認したプログラムではここに設定できるのは「IPアドレス」もしくは「ドメイン名」のみとなっており、プロキシを経由したくないIPアドレスを複数指定する場合は、IPアドレスをひたすらカンマ区切りで列挙する必要があります。たとえば、内部サーバへの接続の際にIPアドレスをそのまま使っている場合、プロキシ経由してほしくないIPアドレスのすべてをここに書き下すことになります。 たとえば"192.168.0.0/24"とか"172.16.0.*"といった、ネットワークアドレスでの指定やワイルドカードでの指定は期待通りの動作になりません。

参照サイト

ちなみに、ここの回答で根拠になっているドキュメントは、wgetのmanページの記述のようです。まさに環境変数そのものの仕様を定めたものは見つからず…。環境変数の扱いは、それぞれのアプリケーションが独自に扱いを決めていて、標準仕様はないということかな。*3*4

ちょっとそれましたが、このような仕様のため、参照サイトでは以下のように、一つ前のブログで書いたようなブレース展開をしたカンマ区切りリスト作成でのno_proxy指定が紹介されています。bashをログインシェルにしている環境で、かつ、/etc/environment ではなく、/etc/bashrc 等に書かないと期待した動作にならないと思いますが、参考までに。

printf -v no_proxy '%s,' 10.1.{1..255}.{1..255};
export no_proxy="${no_proxy%,}";

また上記の例ではもう一つ注意点があり、この例のとおりに「no_proxy」を設定すると、環境変数があまりに長くなりすぎて、以下のようなエラーでvimなどが起動できなくなるという問題があります。なので、とにかく使いそうなIPを全部入れるのではなく、必要最低限の範囲で設定しないといけません。以下のようなエラーが出るようになってしまった場合は「unset no_proxy」で、一旦変数を削除したあとに再設定するのが吉です。

$ vim
-bash: /usr/bin/vim: 引数リストが長すぎます

ちなみに、ブレース展開を使った設定では一つ前のブログのもう一つの手法を使って、以下のようにすることもできます。こちらもbashオンリーです。

no_proxy=$(echo 192.168.1.{1..5})
export no_proxy=127.0.0.1,localhost,${no_proxy// /,}

どちらにしても、環境変数に長大なIPリストができてしまうのは避けられませんが、、、

あまりに長くなる場合は、ドメイン名での振り分けを聞くようにするとか、別の方法を考えたほうがよさそうです。

このネタはこんなところで。

*1:こちらのブログでは /etc/environmentでシステムワイドの環境変数を設定していますが、僕自身はこのファイルでの設定に馴染みがないので、/etc/profileや/etc/bashrcでシェル向けに環境変数を設定しています。/etc/profileや/etc/bashrcはシェルスクリプトなので、スクリプトでの処理結果やbash拡張機能を使った出力結果を環境変数に指定することができます。一方、/etc/environmentは、スクリプトではなく、pam_env.soが読み込むデフォルト環境設定ファイルです。

*2:具体的には社内にOpenStack検証環境を作るときとか

*3:たとえば、こんな記事も見つけました。「HTTP::Tiny 0.32で no_proxyがサポートされました」 http://d.hatena.ne.jp/syohex/20130622/1371884244

*4:環境変数名も大文字、小文字の両方があって、最初に紹介したブログでは両方とも指定していますね。