OSC2012 Tokyo/Fall

                                  お手軽インターネットアクセス制限
                                           - AWK でブラックホール Proxy を作る -


    不快なサイトは見たくない                                            socket_type   =   stream
                                                            wait          =   no
  不快なサイトや広告などがある場合、皆さんはどう                                   user          =   root
していますか?                                                     server        =   /usr/local/bin/blackhole_proxy.awk
  1. 市販ソフトによるブロック                                           disable       =   no
                                                        }
  2. プロバイダによるブロック
  3. hosts によるブロック
  4. ブラウザのアドオンによるブロック                                    xinetd は /ete/service を見ますので、これに TCP
  5. Proxy でブロック                                        の 81 番ポートを加えておきます。
  これらにはそれぞれ一長一短があります。全ての接                               List 3: /etc/service
続機器やブラウザで統一するのは難しく、Proxy では                             blackhole_proxy        tcp/81
HTTPS の通信を制限できません。
                                                            次に proxy.pac は以下のようなものを用意します。
    そうだ! proxy.pac を使おう
  個々のブラウザで制御しつつ一括管理するのには                                List 4: proxy.pac
proxy.pac を 使 い ま す 。 proxy.pac の 正 体 は                 var white_regexp = [
JavaScript ですので、  JavaScript が使えるブラウザで                      ".css",
                                                        ];
あれば使えます。     また、  proxy.pac は Proxy のアドレス
とポートしか返せませんので、ブラックリストに該当                                var black_regexp = [
すれば 1 x 1 ピクセルの透過画像を常に返す Proxy に                            "[^a-z0-9]ad[^a-z]*[^a-z0-9]",
                                                            "[^a-z0-9]affiliate[^a-z]*[^a-z0-9]",
渡します。    この Proxy こそが  「ブラックホール Proxy」                  ];
なのです。    この Proxy に渡すことで "Not Found" と表
示されることも、     画像が  「×」 で表示されることもなくな                      function FindProxyForURL(url, host) {
                                                            for (var i in white_regexp) {
ります。この Proxy は xinetd スーパーサーバーを使                                var regexp = new RegExp(white_regexp[i], "i");
えば、  AWK でも簡単に作れます。        ここでは 81 番ポート                         if (url.match(regexp)) {
を使うように作ってみます。                                                       return "DIRECT";
                                                                }
                                                            }
List 1: /bin/blackhole_proxy.awk
                                                            for (var i in black_regexp) {
#! /bin/gawk -f                                                 var regexp = new RegExp(black_regexp[i], "i");
                                                                if (url.match(regexp)) {
BEGIN {                                                             return "PROXY gauc.no-ip.org:81;";
    RS = "rn"; ORS = "rn";                                  }
                                                            }
    getline;
                                                            return "DIRECT";
    print "HTTP/1.0 200 OK";                            }
    print "MIME-Version: 1.0";
    print "Content-Type: image/gif";
    print "";                                             関数の前で配列でブラックリストを定義したり 、
    printf("x47x49x46x38x39x61x01x00"          shExpMatch ではなく match を使っているので、巷
           "x01x00xf0x00x00xffxffxff"   
           "x00x00x00x21xf9x04x01x00"   
                                                        の proxy.pac とは一風異なるものになっています。ま
           "x00x00x00x2cx00x00x00x00"          た、CSS をブロックすると体裁が崩れてしまうサイト
           "x01x00x01x00x00x02x02x44"          が多いので、    ホワイトリストに加えておくと便利です。
           "x01x00x3bx00");
}
                                                          カスタマイズは自分に合わせよう
                                                         不快と感じるかどうかは個人の主観です。 proxy.pac
 このスクリプトに実行権限を付けて、/usr/local/bin
                                                        であれば自分が不快と思えば簡単に加えることができ
に配置します。また、xinetd の設定を行います。
                                                        ます。しかも、共通でアクセスできる場所に proxy.pac
List 2: /etc/xinetd.d/blackhole_proxy                   を置けば全ての接続機器で同じ設定になります。   さぁ、
service blackhole_proxy                                 ちょっとした工夫で自分に合った快適なインターネッ
{                                                       ト環境を構築してみましょう。

                          日本 GNU AWK ユーザー会 http://gauc.no-ip.org/awk-users-jp/
OSC2012 Tokyo/Fall
    余談                                                       お試しできます!
  proxy.pac は ク ラ イ ア ン ト サ イ ド で 処 理 す る                 この単純な Proxy (実際には httpd ですね) は簡単
JavaScript です。そのため、  あまりにも多い処理を行う                       に設置できますが、お試しのために外部からアクセス
と遅くなったりすることもあります。必要に応じて加                                できるようにしてあります。先述のように 何を不快と
えていくのが良いでしょう。                                           感じるかは個人の主観であるため、 proxy.pac 自体は
  さて、  何故 AWK なのでしょうか? 今回のように常に                         提 供 し ま せ ん が 、 Proxy の 戻 り 値 を gauc.no-
同じものを返すのであれば、Shell でも作成できます。                            ip.org:81 にしていただければ、この Proxy を利用で
しかし、このスクリプトのままだと JavaScript の場合                         きます。    ご利用ください。   (※ただし、  断りなくサービス
にも画像を返すため不具合を生じるかもしれません。                                を停止させていただく場合もあります)
そこで、以下のように拡張してみます。                                        また、   ブースにてデモを行っていますので、        お試しく
                                                        ださい。
List 5: /bin/blackhole_proxy.awk
#! /bin/gawk -f
                                                            Proxy を使った応用
BEGIN {                                                   実際に、私の環境でもこのブラックホール Proxy を
    RS = "rn";    ORS = "rn";                       利用していますが、さらに、 PHP でアクセス元毎の
                                                        proxy.pac の分岐、  LAN 外アクセス時には Ziproxy で
    getline;
                                                        圧縮転送、    Squid によるキャッシュ、 ClamAV によるウ
    request_url     = $2;                               イ ル ス チ ェ ッ ク 、 Google Safe Browsing や
                                                        squidGuard によるさらなるアクセス制限、dnsmasq
    if (request_url ~ /.js$/) {
        is_javascript = 1;                              による DNS のキャッシュなど行っています。         このよう
    } else {                                            に自由なソフトだけで便利かつ安心できる環境を構築
        is_javascript = 0;
                                                        できます。(※これらは上記サービス外です)
    }

    print "HTTP/1.0 200 OK";                               「日本 GNU AWK ユーザー会」について
                                                          日本 GNU AWK ユーザー会は以下のような活動を
    if (is_javascript) {    # JavaScript
        print "MIME-Version: 1.0";
                                                        行っています。
        print "Content-Type: text/javascript";             •   GNU AWK (gawk, gawkextlib) の開発
        print "";                                          •   AWK を便利にするための活動
        print "//";
                                                          GNU AWK (gawk) は外部のライブラリを利用でき
    } else {                # JavaScript 以外
        print "MIME-Version: 1.0";                      るようになりました。XML, PostgreSQL, MPFR など
        print "Content-Type: image/gif";                の 拡 張 を 行 っ て い た xmlgawk の プ ロ ジ ェ ク ト は
        print "";
                                                        gawkextlib と名前を変え、   継続して gawk の外部ライ
        printf("x47x49x46x38x39x61x01x00"   
               "x01x00xf0x00x00xffxffxff"      ブラリ開発活動を行っています。
               "x00x00x00x21xf9x04x01x00"        また、 「USP 友の会」の友好団体として OSC などの
               "x00x00x00x2cx00x00x00x00"   
                                                        イベントや勉強会に参加しています。           ご興味があれば、
               "x01x00x01x00x00x02x02x44"   
               "x01x00x3bx00");                     合わせて参加ください。
    }
}                                                          参考
                                                           •   日本 GNU AWK ユーザー会:
                                                                http://gauc.no-ip.org/awk-user-jp/
 AWK のようなプログラミング言語を使うことで、一
                                                           •   USP 友の会:
貫して簡単に拡張させることができます。                                             http://www.usptomonokai.jp/
 GNU AWK (gawk) には TCP の Socket 通信機能が                      •   Bust Banner Ads with Proxy Auto Config:
                                                                http://www.schooner.com/~loverso/no-ads/
ありますが、   この Socket 通信機能では通信のセッショ
ン管理やタイムアウト処理を行うことができません。
                                                            お問い合わせ先
同様の動作をさせることはできますが、アクセスが集
                                                          本資料に関するお問い合わせは @hi_saito または
中すると不具合が発生してしまいます。          そこで、  xinetd
                                                        hi_saito@yk.rim.or.jp にお願いします。
の TCP Wrapper の機能を使い処理を行っています。
 最近のスマホであれば、3G 回線でも VPN を利用す
ることで proxy.pac を使えますので、    WiFi 環境以外で
もこの Proxy を利用することができます。        ただし、 ここ
では VPN の設定は割愛します。


                            日本 GNU AWK ユーザー会 http://gauc.no-ip.org/awk-users-jp/

日本 GNU AWK ユーザー会チラシ - OSC2012 Tokyo/Fall

  • 1.
    OSC2012 Tokyo/Fall お手軽インターネットアクセス制限 - AWK でブラックホール Proxy を作る - 不快なサイトは見たくない socket_type = stream wait = no 不快なサイトや広告などがある場合、皆さんはどう user = root していますか? server = /usr/local/bin/blackhole_proxy.awk 1. 市販ソフトによるブロック disable = no } 2. プロバイダによるブロック 3. hosts によるブロック 4. ブラウザのアドオンによるブロック xinetd は /ete/service を見ますので、これに TCP 5. Proxy でブロック の 81 番ポートを加えておきます。 これらにはそれぞれ一長一短があります。全ての接 List 3: /etc/service 続機器やブラウザで統一するのは難しく、Proxy では blackhole_proxy tcp/81 HTTPS の通信を制限できません。 次に proxy.pac は以下のようなものを用意します。 そうだ! proxy.pac を使おう 個々のブラウザで制御しつつ一括管理するのには List 4: proxy.pac proxy.pac を 使 い ま す 。 proxy.pac の 正 体 は var white_regexp = [ JavaScript ですので、 JavaScript が使えるブラウザで ".css", ]; あれば使えます。 また、 proxy.pac は Proxy のアドレス とポートしか返せませんので、ブラックリストに該当 var black_regexp = [ すれば 1 x 1 ピクセルの透過画像を常に返す Proxy に "[^a-z0-9]ad[^a-z]*[^a-z0-9]", "[^a-z0-9]affiliate[^a-z]*[^a-z0-9]", 渡します。 この Proxy こそが 「ブラックホール Proxy」 ]; なのです。 この Proxy に渡すことで "Not Found" と表 示されることも、 画像が 「×」 で表示されることもなくな function FindProxyForURL(url, host) { for (var i in white_regexp) { ります。この Proxy は xinetd スーパーサーバーを使 var regexp = new RegExp(white_regexp[i], "i"); えば、 AWK でも簡単に作れます。 ここでは 81 番ポート if (url.match(regexp)) { を使うように作ってみます。 return "DIRECT"; } } List 1: /bin/blackhole_proxy.awk for (var i in black_regexp) { #! /bin/gawk -f var regexp = new RegExp(black_regexp[i], "i"); if (url.match(regexp)) { BEGIN { return "PROXY gauc.no-ip.org:81;"; RS = "rn"; ORS = "rn"; } } getline; return "DIRECT"; print "HTTP/1.0 200 OK"; } print "MIME-Version: 1.0"; print "Content-Type: image/gif"; print ""; 関数の前で配列でブラックリストを定義したり 、 printf("x47x49x46x38x39x61x01x00" shExpMatch ではなく match を使っているので、巷 "x01x00xf0x00x00xffxffxff" "x00x00x00x21xf9x04x01x00" の proxy.pac とは一風異なるものになっています。ま "x00x00x00x2cx00x00x00x00" た、CSS をブロックすると体裁が崩れてしまうサイト "x01x00x01x00x00x02x02x44" が多いので、 ホワイトリストに加えておくと便利です。 "x01x00x3bx00"); } カスタマイズは自分に合わせよう 不快と感じるかどうかは個人の主観です。 proxy.pac このスクリプトに実行権限を付けて、/usr/local/bin であれば自分が不快と思えば簡単に加えることができ に配置します。また、xinetd の設定を行います。 ます。しかも、共通でアクセスできる場所に proxy.pac List 2: /etc/xinetd.d/blackhole_proxy を置けば全ての接続機器で同じ設定になります。 さぁ、 service blackhole_proxy ちょっとした工夫で自分に合った快適なインターネッ { ト環境を構築してみましょう。 日本 GNU AWK ユーザー会 http://gauc.no-ip.org/awk-users-jp/
  • 2.
    OSC2012 Tokyo/Fall 余談 お試しできます! proxy.pac は ク ラ イ ア ン ト サ イ ド で 処 理 す る この単純な Proxy (実際には httpd ですね) は簡単 JavaScript です。そのため、 あまりにも多い処理を行う に設置できますが、お試しのために外部からアクセス と遅くなったりすることもあります。必要に応じて加 できるようにしてあります。先述のように 何を不快と えていくのが良いでしょう。 感じるかは個人の主観であるため、 proxy.pac 自体は さて、 何故 AWK なのでしょうか? 今回のように常に 提 供 し ま せ ん が 、 Proxy の 戻 り 値 を gauc.no- 同じものを返すのであれば、Shell でも作成できます。 ip.org:81 にしていただければ、この Proxy を利用で しかし、このスクリプトのままだと JavaScript の場合 きます。 ご利用ください。 (※ただし、 断りなくサービス にも画像を返すため不具合を生じるかもしれません。 を停止させていただく場合もあります) そこで、以下のように拡張してみます。 また、 ブースにてデモを行っていますので、 お試しく ださい。 List 5: /bin/blackhole_proxy.awk #! /bin/gawk -f Proxy を使った応用 BEGIN { 実際に、私の環境でもこのブラックホール Proxy を RS = "rn"; ORS = "rn"; 利用していますが、さらに、 PHP でアクセス元毎の proxy.pac の分岐、 LAN 外アクセス時には Ziproxy で getline; 圧縮転送、 Squid によるキャッシュ、 ClamAV によるウ request_url = $2; イ ル ス チ ェ ッ ク 、 Google Safe Browsing や squidGuard によるさらなるアクセス制限、dnsmasq if (request_url ~ /.js$/) { is_javascript = 1; による DNS のキャッシュなど行っています。 このよう } else { に自由なソフトだけで便利かつ安心できる環境を構築 is_javascript = 0; できます。(※これらは上記サービス外です) } print "HTTP/1.0 200 OK"; 「日本 GNU AWK ユーザー会」について 日本 GNU AWK ユーザー会は以下のような活動を if (is_javascript) { # JavaScript print "MIME-Version: 1.0"; 行っています。 print "Content-Type: text/javascript"; • GNU AWK (gawk, gawkextlib) の開発 print ""; • AWK を便利にするための活動 print "//"; GNU AWK (gawk) は外部のライブラリを利用でき } else { # JavaScript 以外 print "MIME-Version: 1.0"; るようになりました。XML, PostgreSQL, MPFR など print "Content-Type: image/gif"; の 拡 張 を 行 っ て い た xmlgawk の プ ロ ジ ェ ク ト は print ""; gawkextlib と名前を変え、 継続して gawk の外部ライ printf("x47x49x46x38x39x61x01x00" "x01x00xf0x00x00xffxffxff" ブラリ開発活動を行っています。 "x00x00x00x21xf9x04x01x00" また、 「USP 友の会」の友好団体として OSC などの "x00x00x00x2cx00x00x00x00" イベントや勉強会に参加しています。 ご興味があれば、 "x01x00x01x00x00x02x02x44" "x01x00x3bx00"); 合わせて参加ください。 } } 参考 • 日本 GNU AWK ユーザー会:  http://gauc.no-ip.org/awk-user-jp/ AWK のようなプログラミング言語を使うことで、一 • USP 友の会: 貫して簡単に拡張させることができます。  http://www.usptomonokai.jp/ GNU AWK (gawk) には TCP の Socket 通信機能が • Bust Banner Ads with Proxy Auto Config:  http://www.schooner.com/~loverso/no-ads/ ありますが、 この Socket 通信機能では通信のセッショ ン管理やタイムアウト処理を行うことができません。 お問い合わせ先 同様の動作をさせることはできますが、アクセスが集 本資料に関するお問い合わせは @hi_saito または 中すると不具合が発生してしまいます。 そこで、 xinetd hi_saito@yk.rim.or.jp にお願いします。 の TCP Wrapper の機能を使い処理を行っています。 最近のスマホであれば、3G 回線でも VPN を利用す ることで proxy.pac を使えますので、 WiFi 環境以外で もこの Proxy を利用することができます。 ただし、 ここ では VPN の設定は割愛します。 日本 GNU AWK ユーザー会 http://gauc.no-ip.org/awk-users-jp/