Aug 05

こんにちは。暑いですがみなさんどうお過ごしでしょうか。

tanaka-m です。

投稿一発目は「Gスボット」です。

オープンソースの形態素解析エンジン「MeCab」を利用して、

チャンネルの発言に関係のある名ゼリフを返答します。

・MeCab

http://mecab.sourceforge.net/
Continue reading »

Aug 03

暑い日が続きますが、皆様いかがお過ごしでしょうか。sasaki-kです。

さて、KLabでは社内コミュニケーションツールとして IRC を活用しています。
中にはIRCボットもおり、色々と仕事の役に立っています。

そこで読者の皆様に社内の雰囲気をお伝えするのと同時にお祭り気分を
盛り上げるため、この若手ブログの場をお借りして、今日から2週間程の期間で
KLabの社員が作ったIRCボットを自慢する会を「チキチキIRCボットファイターズ!」
として開催いたします。

作成したボットに特にジャンルは設けてなく

  • 技術の無駄遣い
  • ひらすらウケ狙い
  • やっぱり実用本位

等々・・・法律、公序良俗に反しないものでしたらなんでもOK。

そこで本ブログの読者の皆様に少しだけお手伝いいただければと考えている
ことがあります。hatena book mark あるいは facebook いいね! ボタン
「いいな」と思われた ボット を応援していただけますでしょうか。

この応援の数と社内の投票によって優勝者を決定し、この若手ブログ内で
お知らせしたいと考えております。

皆様、どんなエントリーがあるかお楽しみに!

以下要領となります。 Continue reading »

Jul 26

はじめまして、makki_dです。
四月に新卒として入社したばかりの、若手どころかひよっこの技術者見習いです。

ある日、社内のメーリングリストでOpenCVという単語を出したところ、「ちょっと使ってみたいという人も多いみたいだから、集めて勉強会開かない?」という流れになり、あれよあれよという間に主催することになってしまいました。

KLabでは毎週のように社内勉強会が行われています。このOpenCV勉強会もそんな社内勉強会のひとつです。今回、KLabをもっと広く知ってもらうための試みとして、社外の方をこの社内勉強会に招待することになりました!OpenCVを一緒に勉強してみたい方、KLabに興味のある方、あるいは森タワーの中を見てみたいという方は、ぜひご応募ください。

※募集を締め切りました (7/30追記)
たくさんのご応募ありがとうございました。応募いただいた方には通知のメールをお送りいたします。

テーマ:
OpenCV初心者向け勉強会
開催日時:
2010年8月6日(金) 18:00~21:00
場所:
六本木ヒルズ森タワー20F KLab株式会社 会議室
演題(予定):
  1. ゼロからはじめるOpenCV
  2. 画像ってなぁに?
  3. Pythonデモ使えるOpenCV
  4. OpenCV+Python+物理エンジン=!?
  5. haar-like特徴分類
定員:
5名程度 (先着順)
参加費:
無料 (懇親会を除く)
応募方法:
rd-workshop(_at_)klab.org 宛てに氏名、電話番号(勉強会当日の緊急連絡用)、所属(勤務先、学校等)をお知らせください。その際、タイトルに「OpenCV勉強会参加希望」を含めてください。
※(_at_)をアットマーク@に置き換えてください
その他:
勉強会後に懇親会(自由参加)を予定していますが、こちらは20歳以上に限らせていただきます。
先着順になりますので、参加を希望される方はお早めにご応募ください。

質問等はコメント欄や応募先メールアドレスで受け付けています。遠慮なくお尋ねください。

Jul 26

こんにちは、ponpoko1968です。
前回の続きです。

ボタンを追加する

前回はコントローラの左右の動きを加速度センサーを用いて検知する部分を説明しました。

今回は「前進」「後進」「A」「B」ボタンを追加します。比較的ありがちな部分なのでさらっと説明します。

まず、AnalogRemoteViewControllerクラスにボタンを追加します。
Continue reading »

Jul 16

こんにちは、精神年齢は若手以下かもしれないponpoko1968です。

このたび、弊社ではiPhoneとiPadを連携させて、パーティなどで多人数で楽しめるゲームを開発し、見事IVS LaunchPadの第4位に輝いたのですが、似たようなスキームで、iPhoneをiPad上のリアルタイムゲームのリモートコントローラとして用いることが出来ないか試してみました。

今回は、iPhoneの加速度センサー機能を使って、デバイスの傾きを検出し、iPad上で動作するサーバに送信するアプリを作ってみました。

Continue reading »

Jul 16

opt様が主催されている、ソーシャルアプリコンテストタイアップセミナーにKLabの森本が登壇しました。

森本 隼  KLab株式会社 プロジェクトマネジメント部 リーダー
2006年KLab株式会社にプログラマーとして入社。
自社メディア事業、SNS事業の開発リーダーを経験し、現在ソーシャルアプリ開発のPMとして活躍中。

 
セミナーのテーマは 【LAMPで作るソーシャルアプリの負荷対策 ~アプリとインフラの調和のテクニック~】。現在ソーシャルアプリ周りで最もホットな高負荷対策について、KLabの取り組みを紹介しました。

セミナー風景

会場は満員御礼で立ち見もちらほら。おおよそ150人程度の方に聴講頂きました(感謝!)。
以下のとおり当日の資料を公開しました。(ソーシャルアプリに限らず)高負荷にお困りの方は必見です!
 
Lampで作るソーシャルアプリの負荷対策~アプリとインフラの調和のテクニック~

 
同セミナーは当日Ustreamでも配信されました。ちょっと途中で途切れたりしたので3つに別れてしまいましたが雰囲気は伝わると思います。

タイアップセミナーのハッシュタグ#sac2010も盛り上がりましたのでそちらも合わせてご覧ください。
 
 

Jul 06

yoshida-kです。

社内で仙石CTOより、「このの本を読んでみたい人いないー?」っとの
メールが社内に流れたため、条件反射で手を上げちゃいましたw

表紙

yoshida-kは、最近負荷対策を行ったりすることが多く、「大規模サービス」だったり
「データ構造、メモリ、DB」などのキーワードに敏感に反応してみたりします。

この本は、株式会社はてな様のサマーインターンで、学生向けに行った講義内容を
元にかかれて、大きく分けて3つの話題が書かれています。

1.大規模サービスにおいて発生する「悩み」と悩みに対しての「考え方」の概論
2.大規模サービスの「悩み」に対しての「実践」と「実例」
3.大規模サービスを「運用」する上でのインフラ基礎知識

といった感じでしょうか?

それぞれをピックアップすると

1.では、データが肥大化していく事により、メモリにデータが乗らなくなった事によるdisk IOがmemory IOよりどれくらい重いものか?どれくらい速度が違うのか?なぜ違うのか?といった内容を、図解を含めて解りやすく説明されていたり、OS自体がどのような工夫をしてくれているかなどが解説されています。 (例:diskとmemoryのIOの違いや、OSのページキャッシュについて)
さらに、実際にメモリに乗らなくなった場合に、どうやって対処するのか?や、対処する際の注意点がコレも図解や順序だてたわかりやすい文章で示されています。

2.では、1の内容を踏まえた上で、はてなブックマークのデータを利用した「データ圧縮」や「全文検索」
のプログラムを実際に書きながら「体験」することで「実践」を学んだ上で、必要性や重要性が語られます。

3.では、Webサービスにおける「スケーラビリティ」や「冗長性」、「Webサーバーの効率」についてアプリ開発者が、普段あまり触れることのないインフラ的な知識が語られており、前著の「24時間365日 サーバ/インフラを支える技術」の基礎知識編といった感じです。
また、「クラウド/リアルサーバ」やmemcached、TokyoTyrantなどの「KeyValueストレージ」、「OSの仮想化技術」などの、近年話題となっている技術のメリット、デメリットが語られています。

読んでみた感想ですが、今後KLabに入ってこられる新卒の開発者の方や若手のアプリ開発者にぜひとも一度読んでいただきたい!!
とりあえずWebアプリは作れるが、負荷対策とかはさっぱりデスヨーーって方は特に!

なぜか?
その理由はいくつか(いくつも?w)あります。

1.大規模の規模感の説明、そこから発生する問題の大きな部分から話が始まり、それぞれの問題を一つ一つブレイクダウンした形で解説されていく構成になっており、大規模サービスの負荷の全体像をつかみながら問題を理解していける本の構成

2.ヒットするかどうかが博打的なWebサービスにおいて、開発コストやスピードと安定性のトレードオフが存在する「現実」を前提として書かれているため、知識本で有りながら実用的な内容である点

3.ハードウェア・OSなどのプログラムを書くだけならばあまり気にしないが、高負荷サイトの開発時には気を配らなければならない点が、図解を添えて、どういう動作をしているから、こういう負荷になるといった形でOSやハードウェアに対しての知識がない人にも解るように書かれている点

この辺りが特に気に入った点でしょうか。

普段は慣例だったり、先輩方に教えていただいたknow-howなどでdisk readを避けたり、cacheを利用したりするコードを書いていたyoshida-kですが、この本を通して「なぜ早くなるか」、「なぜ必要か」といった知識を得れたことはとても大きい収穫でした。

あと、急いで読んじゃって中にあった課題にまだチャレンジできていません。
せっかくなのでチャレンジして、またブログに書かせていただこうと思います。

yoshida-k

Jun 30

特に若くもないuchikawa-yです。はじめまして。

KLabの「自由に研究していい」どぶろく制度でやったことを紹介します。

発端

電波時計はJJY(日本の標準電波)等の時刻情報の放送を受信して時刻合わせを行います。この放送は鉄筋コンクリートの建物内ではかなり弱くなるので電波時計はマンションやオフィスビル内では使えない場合が多いです(このことを知らない人が多いのも事実です)。
日本標準時プロジェクト Q&A
日本標準時プロジェクト 標準電波(電波時計)の運用状況

弊社におきましても以下のようなことが起きたことがあります

  1. 会議室などに設置する時計に電波時計を購入した
  2. 初期状態で手動などで正確な時刻を設定したのでしばらくは正常に使える
  3. JJYが受信できないのでそのうちに時刻がずれる 異常動作で大きくずれた時刻を表示したものもあった
  4. 「故障した」と判断されて何台かは廃棄された

悲しい事件ですね。この後、私の雑な調査によれば本社オフィスでは電波時計が正常に動作するのは窓から2~3m程度の範囲に限られることがわかりました。

展開
鉄筋コンクリートの建物内で電波時計を使うための中継装置というものがあります。
Webで調べたところリズム時計工業という会社がJJYの中継装置を製造、CITIZENブランドで販売しているようです。通販などでは入手もできるよう です。
これは2万円程度するようなのでもっと安くなんとかする方法はないか考えました。

思いついたのは外部アンテナを使う方法です。外部アンテナをJJYの電波を受信可能な場所に設置し、同軸ケーブルなどの有線で電波時計の場所 まで送ります。電波時計とケーブルの間は数ターンのコイルで結合させます(具体的には電波時計に内蔵されているアンテナのありそうな部分に導線を巻きつけ ます)。

空中線(アンテナ)
JJYの放送局は日本に2ヶ所あります。福島県から40kHz、福岡県から60kHzで放送されています。東京の場合福島県の40kHzを主に利用しま す。これは長波と呼ばれる帯域で、通常は中波ラジオで使われるようなバーアンテナやループアンテナを使用します。今回は無調整で使用できて、バーアンテナ よりも性能の良いものが作れるマグネチックループアンテナを作ってみました。
これは以下のページに詳しい内容があります。 作成したアンテナは不平衡型です。
受信専用マグネチック・ループアンテナ

配線用のダクトをフレームにしました。サイズは(62cm×48cm)です。これに同軸ケーブル(1.5D-2V)を5回巻いたものをアンテナにして います。 電波時計との間のケーブルも1.5D-2Vです。
ケーブルの特性についてはたとえば 古川電工 メタルケーブルの「同軸ケーブル・高周波同軸ケーブル」のページにある詳細PDFが参考になります。
1.5D-2Vの減衰量は周波数が低くなるほど少なくなり、1MHzで24dB/kmです。つまり100m引き回した場合、減衰は50%以下です。JJYはさらに1桁周波数が低いので室内での使用に限れば気にするほどの減衰はないと思います。

マグネチックループアンテナは通常のループアンテナとは異なりループ面と平行方向に最大感度の指向性を持ちます。 社内のいくつかの場所で試したところ西側や北側に窓のある場所でもアンテナの最大感度方向を窓に向けた場合に高い受信感度が得られることがわかりました。

アンテナ

アンテナ

実験
市販のクロックタイプの電波時計を使って実験してみました。

市販の電波時計(アンテナなし)

市販の電波時計(アンテナなし)

窓からほんの4mほどのところにあるテーブルの上においた電波時計です。電池を一度抜いて完全にリセットかけています。1月1日木曜日だそうで調べてみると2009年のようです。1時間ほど置いてありますがこのように現在の時刻を表示してくれません。

次に先ほどのアンテナを窓際に設置(「実験中」の張り紙をして窓際にあるテーブルの下に立てました。ケーブルは他の社員が足を引っ掛けないようテープで床に固定です)して電波時計に接続します。 接続といってもアンテナのケーブルに細めの導線をつないで輪にして数回時計に巻きつけてあるだけです。

市販の電波時計(アンテナ接続)

市販の電波時計(アンテナ接続)

ごらんの通りに正常に現在時刻が表示されています。なお時計の液晶面右上にある「~~」のような波型表示は受信インジケータらしいです。 外部アンテナを使う方法の有用性が証明できました。

裏側
実は市販の時計を使って確認するのはやりにくいです。設置してしばらく待たないと正常に受信できているかどうかわかりませんし、受信インジケータの表示もアンテナの設置方向を決めるには粒度が荒すぎてあまり役には立ちません。
なので試行錯誤している段階では自作のJJY受信機とトライステート社の 電波時計キット を併用しています。 JJY受信機については以下のページで紹介されているもののコピーです。
長波JJY受信機の製作
こちらでは「手持ちの部品に合わせて作った」というようなことが書かれています。私もOPアンプの入手しやすさや手持ちの部品に合わせて多少アレンジしています。

キットの電波時計

キットの電波時計をアンテナにつないで時刻データを取得

自作のJJY受信機

自作のJJY受信機

Jun 17

umjammer です、

今月末で Twitter API は BASIC 認証を廃止して OAuth オンリーに移行するみたいですね。以前ソーシャルアプリ関連で OAuth を調べていたときに Twitter も試していたのでその時の成果物を公開します。ずいぶん前のことなので忘れていました。危うく旬を逃すところでした。

では、順を追って OAuth を使用した Twitter デスクトップクライアントの作り方を説明します。

Twitter クライアント用のコンシューマーキー、シークレットの取得

  1. この URL で Twitter クライアントアプリ申請を行う
  2. 今回はデスクトップアプリなのでブラウザではない方のチェックボックスをチェックしておく

    twi1
  3. 設定を保存すると画面が変わり、コンシューマーキー、シークレットを取得できる
  4. 同時にアクセストークンリクエストや認可画面URLも取得

    twi2

アクセストークンリクエストや認可画面URLは後述の TwitterOAuthProvider.java で使用しています。

Twitter クライアント用のアクセストークン、シークレットの取得

さきほど取得したコンシューマーキー、シークレットを使用してアクセストークンとシークレットを取得します。Twitter の OAuth のアクセストークンとシークレットは期限が設けられていないみたいですので一回取得すれば今のところずっと使用可能です。

流れとしては、

  1. コンシューマーキー、シークレットを引数にして認可画面をリクエスト
  2. 認可画面のURLが帰ってくる

    tw3
  3. URLの画面をブラウザ上で表示し認可を行なう
  4. ブラウザ画面上にベリファイアが表示される

    tw4
  5. ベリファイアを引数にアクセストークン、シークレットをリクエスト
  6. アクセストークン、シークレットを取得

な感じになります。コードにすると以下になります。


        String consumerKey = "xxxxxxxxxxxxxxxxxxxx";
        String consumerSecret = "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy";

        // コンシューマーを生成
        OAuthUtil oauth = new OAuthUtil(new OAuthConsumer("oob", consumerKey, consumerSecret, new TwitterOAuthProvider()));
        // リクエストトークンを取得
        oauth.doGettingRequestToken();

        // 認可のURLを取得
        System.out.println("以下のURLをブラウザで開いてください。");
        System.out.println(oauth.getAuthorizationURL());

        // アクセストークンを取得
        System.out.print("ベリファイアを入力: ");
        oauth.doGettingAccessToken(oauth.readLineFromStdin());

        //
        System.out.println("accessToken: " + oauth.getAccessToken());
        System.out.println("tokenSecret: " + oauth.getAccessTokenSecret());

Twitter クライアントの作成

アクセストークン、シークレットを取得したところでようやくクライアント作成にかかれます。今回は便利なライブラリ twitter4j を使用しました。今まで取得したキーを引数に API を呼んでやるとサクっと投稿アプリが作れます。あとは GUI 頑張るだけです。



        String consumerKey = "xxxxxxxxxxxxxxxxxxxxx";
        String consumerSecret = "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy";

        String accessTokenString = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
        String tokenSecretString = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";

        TwitterFactory factory = new TwitterFactory();
        Twitter twitter = factory.getInstance();
        twitter.setOAuthConsumer(consumerKey, consumerSecret);
        AccessToken accessToken = new AccessToken(accessTokenString, tokenSecretString);
        twitter.setOAuthAccessToken(accessToken);

        Status status = twitter.updateStatus(statusString);
        System.out.println("Successfully updated the status to [" + status.getText() + "].");

結果です、クライアント名が今回作成したアプリケーション名になっているでしょう?

tw5

今回使用したその他のコードとライブラリ

OAuthUtil.java

import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URISyntaxException; import java.util.HashMap; import java.util.Map; import net.oauth.OAuth; import net.oauth.OAuthAccessor; import net.oauth.OAuthConsumer; import net.oauth.OAuthException; import net.oauth.OAuthMessage; import net.oauth.client.OAuthClient; import net.oauth.client.httpclient4.HttpClient4; /** * OAuthUtil. */ public class OAuthUtil { /** */ protected OAuthConsumer consumer; /** */ protected OAuthClient client; /** */ public OAuthUtil(OAuthConsumer consumer) { this.consumer = consumer; this.client = new OAuthClient(new HttpClient4()); } /** * リクエストトークンを取得する。 */ public void doGettingRequestToken() throws IOException, OAuthException, URISyntaxException { doGettingRequestToken(null); } /** * @before {@link #doGettingRequestToken(Map)} */ private OAuthAccessor requestAccessor; /** * リクエストトークンを取得する。 * * http://.../oauth/request_token */ public void doGettingRequestToken(Map params) throws IOException, OAuthException, URISyntaxException { this.requestAccessor = new OAuthAccessor(consumer); Map parameters = new HashMap(); parameters.put(OAuth.OAUTH_CALLBACK, requestAccessor.consumer.callbackURL); if (params != null) { parameters.putAll(params); } client.getRequestToken(requestAccessor, "GET", parameters.entrySet()); } /** * http://.../oauth/authorize * * @before {@link #doGettingRequestToken(Map)} */ public String getAuthorizationURL() { return consumer.serviceProvider.userAuthorizationURL + "?oauth_token=" + requestAccessor.requestToken; } /** */ private OAuthMessage accessTokenMessage; /** * アクセストークンを取得する。 * * http://.../oauth/access_token * * @param verifier ユーザーとサービスプロバイダ間の認証が済んだことを示すもの * @before {@link #doGettingRequestToken(Map)} */ public void doGettingAccessToken(String verifier) throws IOException, OAuthException, URISyntaxException { if (requestAccessor == null) { throw new IllegalStateException("call after doGettingRequestToken"); } OAuthAccessor accessor = new OAuthAccessor(consumer); Map parameters = new HashMap(); parameters.put("oauth_token", requestAccessor.requestToken); parameters.put("oauth_verifier", verifier); accessor.tokenSecret = requestAccessor.tokenSecret; this.accessTokenMessage = client.getAccessToken(accessor, "GET", parameters.entrySet()); } /** * @before {@link #doGettingAccessToken(String)} */ public String getAccessToken() throws IOException { if (accessTokenMessage == null) { throw new IllegalStateException("call after doGettingAccessToken"); } return accessTokenMessage.getParameter("oauth_token"); } /** * @before {@link #doGettingAccessToken(String)} */ public String getAccessTokenSecret() throws IOException { if (accessTokenMessage == null) { throw new IllegalStateException("call after doGettingAccessToken"); } return accessTokenMessage.getParameter("oauth_token_secret"); } /** * 標準入力から一行取得して返す。 * * @return 入力された文字列 */ public String readLineFromStdin() throws IOException { String line = null; BufferedReader stdReader = new BufferedReader(new InputStreamReader(System.in)); line = stdReader.readLine(); // ユーザの一行入力を待つ stdReader.close(); return line; } /** * OAuth認証サービスにアクセスする。 */ public InputStream getResource(String url) throws IOException, OAuthException, URISyntaxException { Map params = new HashMap(); params.put("oauth_token", getAccessToken()); OAuthAccessor accessor = new OAuthAccessor(consumer); accessor.tokenSecret = getAccessTokenSecret(); OAuthMessage response = client.invoke(accessor, url, params.entrySet()); return response.getBodyAsStream(); } public void printStream(InputStream is) throws IOException { byte[] data = new byte[8192]; while (is.available() > 0) { int r = is.read(data, 0, data.length); System.err.write(data, 0, r); } } }

TwitterOAuthProvider.java

import net.oauth.OAuthServiceProvider; /** * TwitterOAuthProvider. */ public class TwitterOAuthProvider extends OAuthServiceProvider { public TwitterOAuthProvider() { super("http://twitter.com/oauth/request_token", "http://twitter.com/oauth/authorize", "http://twitter.com/oauth/access_token"); } }

その他のライブラリ

  • net.oauth.core/oauth-20090617
  • net.oauth.core/oauth-consumer-20090617
  • net.oauth.core/oauth-httpclient4-20090617
  • net.homeip.yusuke/twitter4j-core-2.1.*

まとめ

OAuth や Twitter API にはライブラリが揃っていますので簡単に OAuth アプリが作れました。

ただ OAuth を使用したデスクトップクライアントソフトにはここに書かれているような問題があります。悪用すればクライアントなりすましも可能でしょう。

以前紹介した OpenFeint API も OAuth を使用しています。iPhone や iPad のアプリは .ipa ファイルとして iTunes ライブラリに保存されていますが、単なる .zip ファイルなので解凍して中を覗くことができます。皆さん暗号化とかされてるみたいですのでまだシークレットキーを発見したことはないのですが、リバースエンジニアリングされればもしかすると発見できるかもしれません。そうなるとハイスコア改ざんやトロフィーコンプリートなども簡単にできちゃいます。

私もいろいろ考えたのですがいい回避策が思いつきません。皆さんなにか良い知恵があればお教えください。あとは OAuth WRAP に期待ですか。

訂正 2010-06-18
一枚目の画像が説明と異なっていたので差し替えました。

May 26

はじめまして、インなんとかさんです。いやうそです。ごめんなさいよく知らないんですそのアニメ。

私たちKLabには、六本木本社や大阪、福岡の各事業所以外に、遠隔地から参加して勤務している社員が何名かおりまして、私はそのうちの一人です。普段の業務はメールはもちろんJabberやIRCやSkype、WikiやTracなど様々なツールを用いて連絡を取り合いつつ、通常勤務の人たちと変わらず日々はたらいております。

さてそんな折、自宅のネットワーク環境はやっぱりまあある程度充実させておきたいなと思うわけです。ましてやネットワークやLinuxをいじって飯食ってる手前、ただ漫然と○○バシカメラで買ってきたブロードバンドルータをつなげてわーいらくちんだなあえへへーとか言ってるんじゃいかんと思ったわけです。どうやってISPとつなげてどうやってパケットがルータを通って、とか見てみたいじゃないですか。

というわけでやってみました。Linuxマシンでルータづくり。

まず機材選定というか、PCを組まなければいけないわけですが最初から狙いはAtomで組もうと定めてました。mini ITXなら静音で小型のやつが組めるだろうなと。でどうせルータ用途に専念させるなら拡張性は無視でいいし、ディスク容量もほとんど要らないので取捨選択もしやすかったです。

http://www.intel.co.jp/products/desktop/motherboards/D510MO/D510MO-overview.htm
Intel® Desktop Board D510MO - Overview

私が選んだのはScythe製BM639。縦置き可能なほうが都合よかったので選びました。

http://www.scythe.co.jp/case/bm639.html
株式会社サイズ | 商品詳細 |BM639

メモリやHDDはそこそこに、あとせっかくルータなのでNICを1枚買ってきてONUと直結用にしました。

http://buffalo.jp/products/catalog/item/l/lgy-pci-gt/
LANアダプタ|LGY-PCI-GT

そして組み立ては無難に完了。LinuxのインストールはUSBメモリを使いました。

http://www.jp.debian.org/releases/lenny/i386/ch04s03.html.ja#usb-copy-flexible
4.3.2. ファイルのコピー — 柔軟な方法 [www.jp.debian.org]

USBメモリを使ってインストールイメージを作成するのには、上記URLの方法を参考にしました。設定項目を入力していけばほとんど詰まることなくいけましたよ。

あとは設定ですね。まずはsysctl周り。

net.ipv4.ip_forward = 1

これがないとはじまりません。

続いてiptablesなんですが、最近のDebianでは/etc/network/if-pre-up.d/以下に配置するべきと聞きまして、下のようなスクリプトを用意しました。

#!/bin/sh

IPTABLES='/sbin/iptables'

LOCAL_IF=eth0
LOCALNET='x.x.x.x/yy'

##########
# initialize

$IPTABLES -F
$IPTABLES -X
$IPTABLES -Z

$IPTABLES -t nat -F POSTROUTING

$IPTABLES -P INPUT DROP
$IPTABLES -P FORWARD DROP
$IPTABLES -P OUTPUT ACCEPT

##########

$IPTABLES -A INPUT -j ACCEPT -m state --state ESTABLISHED,RELATED
$IPTABLES -A INPUT -j ACCEPT -i lo
$IPTABLES -A INPUT -j ACCEPT -s $LOCALNET
$IPTABLES -A INPUT -j ACCEPT -p tcp --dport 1723
$IPTABLES -A INPUT -j ACCEPT -p 47

$IPTABLES -A FORWARD -j ACCEPT -m state --state ESTABLISHED,RELATED

##########

$IPTABLES -N outer_local

##########

$IPTABLES -N local_outer
$IPTABLES -A local_outer -j ACCEPT -s $LOCALNET

##########
# nat

$IPTABLES -t nat -A POSTROUTING -j MASQUERADE -s $LOCALNET -o ! $LOCAL_IF

##########
# main table

$IPTABLES -A FORWARD -j outer_local -i ! $LOCAL_IF -o $LOCAL_IF
$IPTABLES -A FORWARD -j local_outer -i $LOCAL_IF

$IPTABLES -A INPUT -j outer_local -i ! $LOCAL_IF

さて最後にPPPoEの設定、こちらはマルチセッションでつないでいるので、以下のようなファイルを二つ、それぞれ/etc/ppp/peers/配下に置きました。

# /etc/ppp/peers/ISP_A
noipdefault
defaultroute
hide-password
lcp-echo-interval 20
lcp-echo-failure 3
connect /bin/true
noauth
persist
mtu 1492
noaccomp
default-asyncmap
plugin rp-pppoe.so eth1
user "aaa@bbb"
usepeerdns
# /etc/ppp/peers/ISP_B
noipdefault
nodefaultroute
noproxyarp
hide-password
lcp-echo-interval 20
lcp-echo-failure 3
connect /bin/true
noauth
persist
mtu 1492
noaccomp
default-asyncmap
plugin rp-pppoe.so eth1
user "xxx@yyy"

パスワードファイルが必要なので、/etc/ppp/{chap-secrets,pap-secrets}に次の内容で配置します。

"aaa@bbb" * "ccc"
"xxx@yyy" * "zzz"

最後に、自動接続させるために/etc/network/interfacesに下記を追加。

auto eth1
iface eth1 inet static

auto ppp0
iface ppp0 inet ppp
  pre-up /sbin/ifconfig eth1 up
  provider ISP_A

auto ppp1
iface ppp1 inet ppp
  pre-up /sbin/ifconfig eth1 up
  provider ISP_B

最後に、マルチセッションの使い分けのためのルーティング設定を追加しました。ISP_Bの方の接続は固定IPアドレスになっていて、本社との間のsshやVPN接続を行う際の認証にこのIPアドレスでのフィルタリングも行っているためです。

#!/bin/sh

if [ "x$PPP_IFACE" = "xppp1" ]; then
  ip route add a.a.a.a dev $PPP_IFACE
  ip route add b.b.b.b dev $PPP_IFACE
fi

以上の設定で無事Linuxルータが稼働しました。でも、これはまだまだ最初の一歩にすぎません。せっかく市販のブロードバンドルータからLinuxに入れ替えたからには、中をいろいろといじりやすい環境になったわけですからまだまだいろいろと試してみたいじゃないですか。次回以降、これにさらに手を加えて自分なりにあそんでみたいと思います。