仙石浩明の日記

2006年4月18日

VPN-Warp 入門編 (3)

前回は、ssh のポートフォワーダと比較して、 VPN-Warp には次の特長があることを説明しました。

  1. ログインアカウントが不要
  2. アクセス対象はリレーサーバのみ

例えばローカルホストの 8080番ポートを、 リモートの intra:10080 へフォワードする場合、 次のように、ローカルホストで stone を、リモートホストで relayagent を、 それぞれ走らせます。

ローカルホスト         リレー           リモートホスト
    stone ─────→ サーバ ←──── relayagent─→ intra
  8080番ポート …………………………………………………→ 10080番ポート

stone も、relayagent も、リレーサーバに対しては 「クライアント」であることに注意してください。 また、ローカルホスト、リモートホスト、リレーサーバ、 いずれにおいても、ssh の場合のようなログインは必要ありません。

必要なのは、SSL クライアント認証だけで、 stone/relayagent はクライアント証明書を使って リレーサーバへアクセスする、というわけです。 実際、リレーサーバは stone/relayagent にとって、 普通の https サーバのように見えます。 リレーサーバは、stone/relayagent 双方から SSL 接続を受付け、 もし同一のクライアント証明書を持っている組があれば、 それらを結び付ける役割を果たします。

具体的な設定方法

stone/relayagent それぞれの具体的な設定方法を見ていきましょう。

stone の設定

stone の設定ファイルは次のような感じになります:

-q key=private.pem
-q cert=cert.pem
relay.klab.org:443/ssl,http localhost:8080 "GET / HTTP/1.1" --
  • -q key= から始まる行は、SSL 証明書の秘密鍵ファイル、
  • -q cert= から始まる行は、SSL 証明書の公開鍵ファイルの指定です。
  • relay.klab.org:443 はリレーサーバの指定、
  • 最後の localhost:8080 がローカルホストで listen するポートの指定です。

このような設定を行なうと、 stone は 8080番ポートで受けた接続を、 「https リクエストに乗せて」リレーサーバへ転送します。

「https リクエストに乗せて」というのはどういうことかというと、 例えば 8080番ポートに接続して「abcdefg」というデータを送信したとすると、 stone は以下のようなデータを、SSL で暗号化してリレーサーバへ送ります:

GET / HTTP/1.1

abcdefg

あまり「https リクエスト」のようには見えませんが (^^;)、 最初の一行がリクエストヘッダで、 空行をあけて、リクエストボディが続いている、と見なすこともできます。

実をいうとリクエストヘッダ (のようなもの) を送り終わった時点で、 任意のデータの送受信が可能で、 送信したデータデータはそのまま relayagent へ伝わります。 つまり、 8080番ポートが、relayagent へフォワードされる、というわけです。

relayagent の設定

relayagent の設定ファイルは次のような感じになります:

-n
-k private.pem
-c cert.pem
relay.klab.org:443
intra:10080
  • -n は、relayagent をポートフォワーダとして使う、という意味です。
  • -k から始まる行は、SSL 証明書の秘密鍵ファイル、
  • -c から始まる行は、SSL 証明書の公開鍵ファイルの指定です。
  • relay.klab.org:443 はリレーサーバの指定です。
  • 最後の intra:10080 がポートフォワード先の指定です。

このような設定で relayagent を実行すると、 relayagent は、リレーサーバに対して以下のような「ポーリング」を https を装って行ないます。

GET /KLAB/poll HTTP/1.1
X-Ver: 2 relayagent.cpp,v 1.32 W (TAKUMI)

「X-Ver:」の次の数字「2」で、relayagent - リレーサーバ間の プロトコルのバージョン番号を伝えています。 続く「relayagent.cpp,v 1.32 W (TAKUMI)」は単に relayagent のバージョンを (トラブル時の解析用として) 伝えているだけで、通常は参照されません。

このリクエストヘッダ (のようなもの) を送り終わると、 リレーサーバは次のようなレスポンスを返します:

HTTP/1.1 200 OK
X-Customer: nusers=10&type=3&expire=1262271599&digest=0123456789abcdef0123456789abcdef

この、https レスポンスヘッダ (のようなもの) を受信した後、 relayagent はレスポンスボディ待ち状態 (ポーリング状態) になります。 この状態の時、 同じ証明書を持つ stone からの接続があると、 その情報がレスポンスボディとして送られてきて、 relayagent はそれを受けて intra:10080 へ接続を行ない、 stone と intra:10080 との間の通信が確立する、というわけです。

Filed under: システム構築・運用 — hiroaki_sengoku @ 16:42
2006年4月17日

新卒採用 (1)

大学4年/大学院2年の学生さんに、 どれだけこのページを読んでもらえてるか分からない (^^;) のですが、

KLab(株) CTO 仙石 (KLabセキュリティ(株) CTO を兼務) と語る、
「技術者の成長にとって一番役に立つ会社」
「技術者が自ら伸びていくことができる会社」とは?

と題する会社説明会が開催されるようです。

日時: 5/9(火) 13:30~15:00
場所: KLab(株) 本社会議室 (六本木ヒルズ森タワー 20F)

会社説明会といいつつ、 要は私といろんな話題についてお話しましょう、 というノリですので、 私の日記 (CTO日記もよろしく) を見て、 波長が合いそうだと思ったかた、 ぜひ登録をお願いします。

4/27追記: 上記説明会は満席につき、現在は 5/15実施の説明会への登録を受付中です
5/8 追記: 上記説明会は満席につき、現在は 5/30実施の説明会への登録を受付中です

Filed under: 技術者の成長 — hiroaki_sengoku @ 17:11
2006年4月17日

オープンソースにこだわる

多くの会社と同様、KLab (および KLabセキュリティ) でも、 出来る限りオープンソースを利用するようにしています。 我々がDSASと呼んでいる システムインフラは、完全にオープンソースベースとなっており、例えば 「ファイアウォール兼負荷分散器兼ルータマシン」も Linux ベースとなっております。

なぜオープンソースにこだわるのか?

佐野氏のコラムに、 オープンソースにこだわる人の理由って正しい?:

    > オープンソースにこだわる人に理由を聞くと普通
    >
    >  1.無料だから
    >  2.大勢の人が使っているからバグが少ないと思われる
    >  3.ソースコードが公開されているから安心
    >
    > という答えが返ってきます。1と2はまあその通りだと思います。
    > しかし3は個人的にちょっと疑問です。
    > オープンソースにこだわっている人で、オープンソースソフトウェアの
    > ソースコードを実際に分析したことがある人って
    > どのくらいいるのでしょうか。
      ……
    > なのでオープンソースにこだわる理由を聞かれたらかっこいいこと
    > 言わずに素直に「無料だし機能に不満もないから」くらいにしておくのが
    > よいのではないでしょうか。

という問いかけがありました。さすが佐野さん、的を射た厳しいご意見ですね。 正直な話、KLab もオープンソースを利用しているといっても、 スミからスミまで分析しているわけではありませんし、 「無料だし機能に不満もないから」という面もあることは否定しません。 しかし、お客様にサービスを提供するという立場としては、 もう少し積極的な理由も持ちたいところです。

責任あるシステム運用を実現するためのオープンソース

システムにベンダ任せのブラックスボックスな部分があると、 その部分が原因の障害への対応は遅くなりがちですし、 原因究明を完全に行なうことができなければ、 再発防止策も対症療法的なものになりがちです。 これでは自信を持ってお客様にサービスを提供することができません。

KLab も以前は箱モノの負荷分散機を利用していたのですが、 クリティカルなバグに散々悩まされました。 この箱モノは L2処理に問題があり、 通信不良が発生するケースがあったのです。 もちろんベンダへは症状を報告していたのですが、 完全な対策には至らず、なんとか運用でカバーしていました。

これでは、いつ症状が再発するか分からず 精神衛生上もよろしくありません。 そこで、LVS (Linux Virtual Server) を使って Linux ベースの負荷分散機を 構築することにしました。 むろん、LVS のソースコードの全てを完全に把握しつくし、 LVS プロジェクトに貢献できるようになるまでには、 まだまだ道程が遠いのですが、 再現可能な障害であれば問題の所在を見つけ出せる程度の レベルには達することができていると思っています。 しかも、実はこうやって自前で構築した負荷分散機の方が、 それまで使っていた箱モノよりずっと安定して運用できてしまったのです。

ベンダの都合に振り回されないためのオープンソース

プロプライエタリなソフトウェアを使っている場合は、 ベンダがサポートを停止するリスクというのも考えておかねばなりません。 ベンダがサポートを止めたことを理由に、 弊社のお客様に対するサービス提供を止める、というやり方も 無いわけではありませんが、 技術会社を標榜する KLab としては、 あまりそういう言い訳はしたくありません。

すると、 ベンダがサポートを止めたときのことまで考えておく必要がありますが、 あいにくソフトウェアの使用許諾というのは一般に不平等契約で、 ソフトウェアを使用する側には打つ手がないことが多いようです。 ベンダの都合に振り回されるよりは、 いざとなったら自前で解決できるよう、 ソースがオープンになっているソフトウェアを選ぶ方が 結果的に楽といえるのではないでしょうか。

なんかプロプライエタリって馬鹿みたいだな」 (ここギコ!) で、

    > プロプライエタリなソフトの方がよっぽどリスクだらけちゃうの?
    > わざわざクソ高い金払うのに、と思えてくる。

という意見も出ているように、 ベンダのサポートがアテになるケースばかりとは限りません。

自由なシステム構築を実現するためのオープンソース

どんなに柔軟性が高いソフトウェアでも、 カスタマイズで可能な範囲というのはタカが知れています。 ソースを改変することによって得られる自由とは雲泥の差でしょう。

KLab としては、 他社では行なっていないような方法で、 耐故障性を向上させたり、 性能を向上させたり、 より低コストな運用を実現したり することによって、 差別化をはかっていきたいわけで、 そうなるとベンダの製品を使うよりは、 オープンソースを使うべき、という選択になります。

実際にどのようにオープンソースを活用しているかは、 DSAS開発者の部屋などで 紹介していきたいと思っておりますし、 オープンソースを活用していく過程で我々のレベルが上がって、 オープンソース界に貢献できるようになれれば、 それは我々にとって望外の幸であり、 それを目指して研鑽を積んでいく所存です。

Filed under: システム構築・運用,技術と経営 — hiroaki_sengoku @ 06:19
2006年4月16日

getnameinfo のバグ? (2)

昨日、getnameinfo の問題について述べたが、 念のため、glibc のソースを確認してみた。 手元に展開してあった glibc-2.3.5 を見ると、 glibc-2.3.5/inet/getnameinfo.c の 440行目で、

      case AF_LOCAL:
        strncpy (serv, ((const struct sockaddr_un *) sa)->sun_path, servlen);
        break;

とある。sun_path が 0 終端されていないと、 sun_path が実際に何バイト確保されているかとは関係なく、 servlen バイトがコピーされてしまう。

getnameinfo の salen 引数のチェックは、 同じく getnameinfo.c 182行目の、

    case AF_LOCAL:
      if (addrlen < (socklen_t) (((struct sockaddr_un *) NULL)->sun_path))
        return EAI_FAMILY;
      break;

だけであった。 つまり sun_path の部分が 0 バイトでもエラーにならない。

今回の問題とは関係ないが、

(socklen_t) (((struct sockaddr_un *) NULL)->sun_path))

という書き方は参考になる。 stone.c では

(((struct sockaddr_un*)sa)->sun_path - (char*)sa)

と書いていたのだが、 NULL を使えば簡潔に書ける、 というのは目から鱗だった。

Filed under: stone 開発日記 — hiroaki_sengoku @ 08:17
2006年4月16日

交通広告: 個人情報スキャナ P-Pointer

KLabセキュリティの主力製品である、 個人情報スキャナ 「P-Pointer」 の広告を、4/14 から一ヶ月間、地下鉄に出すことにしてみました。 インターネット広告が伸びつつある今、 時代に逆行しているようですが、 交通広告という従来型の広告がどれだけ効果があるか楽しみです。

東京メトロ 地下鉄 半蔵門線 に掲載した、 P-Pointer の 窓上広告:
P-Pointer 交通広告

一般的には、窓の上の広告なんて (見上げないと見えないから) 誰も見ないだろうということで、 吊り広告などに比べると安価な窓上広告なのですが、

      我々がリーチしたい人達はラッシュの時間帯に乗る通勤客
        ↓
      ラッシュ時間帯の田園都市線は死ぬほど混む
        ↓
      とても新聞とかを読めるような状態ではない
        ↓
      地下鉄だから景色を見るわけにもいかない
        ↓
      仕方ないんで窓の上の広告でも見るか

となるので、 混雑する通勤路線であればあるほど窓上広告は効果的だと想像した次第です。 私自身、毎朝毎晩、ラッシュの田園都市線 (渋谷から西へ伸びる東急路線です。地下鉄半蔵門線と相互乗り入れしています) で通勤していて、 窓上広告を見る機会が多かったりしますし、 沿線にはいわゆる「IT業界」の会社が多く、 「個人情報」にセンシティブな人が多いだろう、 ということで半蔵門線を選びました。

Filed under: 技術と経営 — hiroaki_sengoku @ 06:40
2006年4月15日

getnameinfo のバグ? (1)

UNIX で TCP接続を accept したとき、そのソケット sd に対して

struct sockaddr_storage ss;
struct sockaddr *from = (struct sockaddr*)&ss;
socklen_t fromlen = sizeof(ss);
getpeername(sd, from, &fromlen);

などとすれば、接続元のアドレスが from に返る。 UNIXドメインソケットを listen し accept した場合は、

from->sa_family ← AF_UNIX
fromlen ← 2

という値が返るようだ。

ところが、
この返り値を getnameinfo に与えると、 fromlen で指定したサイズを超えて UNIX ドメインソケットのファイル名を読もうとする 問題があるようだ。

たとえば次のようなテストプログラムを書いてみる:

#include <stdio.h>
#include <sys/socket.h>
#include <netdb.h>
#include <sys/un.h>
#define STRMAX  256
main() {
    struct sockaddr *sa;
    socklen_t salen;
    struct sockaddr_un sun;
    char name[STRMAX+1];
    char serv[STRMAX+1];
    int err;
    bzero(name, STRMAX+1);
    bzero(serv, STRMAX+1);
    sa = (struct sockaddr*)&sun;
    salen = sizeof(sun);
    sun.sun_family = AF_UNIX;
    strcpy(sun.sun_path, "/tmp/sock");
    salen = sizeof(sa_family_t);
    err = getnameinfo(sa, salen, name, STRMAX, serv, STRMAX, 0);
    printf("salen: %d, err: %d, name: '%s', serv: '%s'\n",
           salen, err, name, serv);
}

salen は 2 であるので、 sun.sun_path の部分の値は無視すべきであるのに、 serv には、"/tmp/sock" の値が返ってしまう。 sun.sun_path の部分が初期化されていなければ、 不定値が返るだろう。

実際、stone では struct sockaddr_storage を初期化せずに getpeername を呼び出して長さ 2 の struct sockaddr_un を受け取り、 これを getnameinfo の引数として与えると、 dserv に不定値が返ってきてしまった。

本来ならば、getnameinfo は長さ 0 のパス名を返すか、 あるいは UNIX ドメインソケットは扱わない、 ないしは長さが異常ということで EAI_FAMILY を返すか、 どちらかであるべきではなかろうか。 少なくとも glibc-2.3.5 と、glibc-2.2.5 では、 この問題があることを確認した。

とりあえず、stone は AF_UNIX のときは getnameinfo を呼ばずに sun_path を dserv へコピーするように修正した。

$Id: stone.c,v 2.2.2.19 2006/04/14 23:35:18 hiroaki_sengoku Exp $

Filed under: stone 開発日記 — hiroaki_sengoku @ 09:58
2006年4月15日

VPN-Warp 入門編 (2)

前回は、ssh のポートフォワーダには次の二点の欠点がある、 というお話をしました。

  1. リモートホストにログインアカウントが必要
  2. リモートホストへアクセスできることが必要

すなわち、ssh でポートフォワードを行なう場合、例えば

ssh -L 8080:intra:10080 remote "sleep 1d"

といった感じで実行しますが、ssh ログイン先である remote の セキュリティレベルを下げる要因となってしまう、という欠点です。

欠点 (1) を VPN-Warp ではどのように解決しているか

VPN-Warpでは、リモートマシンにログインアカウントは必要ありません。 リモートマシンに必要なのは、リレーエージェントと呼ばれるプログラムを 走らせることだけで、Linux 上でも Windows 上でも走らせることができますし、 Windows 版は、NT サービスとして実行することも可能です。

VPN-Warp ではユーザ管理をリレーサーバ上の DB で行なっていますので、 100万人規模のユーザに対しても余裕でサービスできます。 リモートマシンではユーザ管理を行なう必要がないので、 リレーエージェントを走らせるために必要な設定は、 ポートフォワード先 (上述の例だと intra:10080) の設定だけです。

リレーエージェントが行なうのは、 ポートフォワードに限定されているので、 セキュリティリスクを最小限に抑えることができます。

欠点 (2) を VPN-Warp ではどのように解決しているか

VPN-Warpでは、リモートマシンに直接アクセスする代わりに、 中継専門のリレーサーバを用います。 リモートマシン上で走らせるリレーエージェントが、 リレーサーバへアクセスしてリレーサーバと連係動作することによって、 ローカルホストがアクセスする対象はリモートマシンではなく リレーサーバになります。 ssh と VPN-Warpの違いを図で書くと次のような感じになります:

ssh のポートフォワードの場合:

ローカルホスト                          リモートホスト
    ssh ─────────────────→ sshd  ─→ intra
  8080番ポート …………………………………………………→ 10080番ポート

VPN-Warpの場合:

ローカルホスト         リレー           リモートホスト
    stone ─────→ サーバ ←──── relayagent─→ intra
  8080番ポート …………………………………………………→ 10080番ポート

図中 relayagent というのがリレーエージェントです。 VPN-Warpの場合、リモートホストへは外部からアクセスする必要が ないことに注意して下さい。 代わりに外部からのアクセスを受け付けるのは「リレーサーバ」です。

ssh の場合はリモートホストが外部からの攻撃に晒されるリスクがあるわけですが、 VPN-Warpの場合は、外部からの攻撃に晒されるのはリレーサーバだけです。

そしてリレーサーバは、KLab など VPN-Warp 提供側が運営するので、 VPN-Warp ユーザは外部からの攻撃を気にする必要がありません。

また、リレーサーバ自体は単にデータを右から左へデータを流すだけで、 ssh ログインアカウントのような侵入の足掛かりになるようなものは 何もありません。 もちろんリレーサーバは、専用のディレクトリへ chroot してから、 リレーサーバ専用のユーザ権限で実行するようにしています。

Filed under: システム構築・運用 — hiroaki_sengoku @ 07:01
2006年4月14日

DB サーバのセキュリティ向上策 (6)

DB サーバのセキュリティ向上策 (3)」では、 どのユーザが UNIX ドメインソケットにアクセスしたか特定するために、 ユーザごとにソケットを作成しました。 しかし Linux などの OS では、UNIX ドメインソケットに限り アクセス元のユーザを getsockopt(2) で調べることができるので、 ソケット一つだけでどのユーザからのアクセスか区別することができます。

例えば以下のように getsockopt の引数に SO_PEERCRED を指定することにより、 ucred 構造体にアクセス元のユーザの情報が格納されます:

struct ucred cr;
int len = sizeof(cr);
int ret = getsockopt(sd, SOL_SOCKET, SO_PEERCRED, &cr, &len);
if (ret == 0) {
    struct passwd *passwd = getpwuid(cr.uid);

    ...

}

したがって、UNIX ドメインソケットを listen し、 そのソケットへ接続があったら、 それを DB サーバへ通信を監視しつつ中継するプログラム dbrelay において、 上記のように getsockopt(2) を使ってアクセス元ユーザを特定し、 通信の監視によって得られた DB ユーザ名と一致したら中継を継続し、 一致しなかったら通信を遮断する、ということが可能になります。

もちろん、各ユーザが直接 DB サーバへアクセスしないよう、 dbrelay からのアクセス以外は OUTPUT チェインで通信を却下します。

このような仕掛けを、ラック内の全サーバに仕込むことにより、 各ユーザは同名の DB ユーザでのみ DB サーバへ、 UNIX ドメインソケット経由でアクセスできます。

通信の監視をクライアント側でなく、 DB サーバ側で行ないたい場合は、 クライアント側の dbrelay では アクセス元のユーザ名をサーバ側へ伝えるだけにして、 通信の監視および通信の遮断はサーバ側で行なわせることもできます。

最新版 の stone には アクセス元のユーザ名をサーバ側へ伝える機能があるので、 例えばクライアント側で次のように stone を実行します。

stone dbserver:12345/http /tmp/db.sock '\U'

「/http」の指定と「'\U'」が、ユーザ名をサーバ (dbserver:12345) へ 伝える設定です。例えばユーザ sengoku が UNIX ドメインソケット /tmp/db.sock にアクセスすると、stone はまず

Apr 14 07:54:36.809789 16384 3 5>6 73 65 6e 67 6f 6b 75 0d  sengoku.
Apr 14 07:54:36.809828 16384 3 5>6 0a 0d 0a                 ...

を dbserver:12345 へ送信し、その後は /tmp/db.sock から dbserver:12345 への 中継が行なわれます。 したがってサーバ側ではまず最初に送られてきたユーザ名を受け取り、 その後は通信を監視しつつ 12345 番ポートから DB サーバへの中継を行なえばよいわけです。

Filed under: stone 開発日記,システム構築・運用 — hiroaki_sengoku @ 08:13
2006年4月14日

SO_PEERCRED

UNIX ドメインソケットならば、カーネルはどのユーザが そのソケットに connect したか知っているはずで、 きっと getsockopt(2) でユーザID が取得できるに違いない、 と思ってカーネルソースを見ていたら SO_PEERCRED を発見。

ついでに SO_PEERCRED をググってみたら、 PostgreSQL や w3m では、 既に SO_PEERCRED を使った認証をサポートしていることが判明。 負けじと stone にも実装してみる。

$Id: stone.c,v 2.2.2.18 2006/04/13 09:02:15 hiroaki_sengoku Exp $

README から引用:

        stone [-C <file>] [-P <command>] [-Q <options>] [-N] [-d] [-p] [-n]
              [-u <max>] [-f <n>] [-l] [-L <file>] [-a <file>] [-i <file>]
              [-X <n>] [-T <n>] [-r]
              [-x <port>[,<port>][-<port>]... <xhost>... --]
              [-s <send> <expect>... --]
              [-b [<var>=<val>]... <n> <master>:<port> <backup>:<port>]
              [-B <host>:<port> <host1>:<port1>... --]
              [-I <host>]
              [-o <n>] [-g <n>] [-t <dir>] [-D] [-c <dir>]
              [-q <SSL>] [-z <SSL>]
              [-M install <name>] [-M remove <name>]
              <st> [-- <st>]...

        ...

        <st> は次のいずれかです。<st> は「--」で区切ることにより、複数個
        指定できます。

        ...

        (4)        <host>:<port>/http <request> [<xhost>...]
        (5)        <host>:<port>/proxy <header> [<xhost>...]

        (4) は、http リクエストにのせて中継します。<request> は HTTP 1.0 
        で規定されるリクエストです。リクエスト文字列中、「\」はエスケー
        プ文字であり、次のような置き換えが行なわれます。

                \n        改行 (0x0A)
                \r        復帰 (0x0D)
                \t        タブ (0x09)
                \\        \    (0x5C)
                \a        接続元の IP アドレス
                \A        「接続元の IP アドレス」:「ポート番号」
                \d        接続先の IP アドレス
                \D        「接続先の IP アドレス」:「ポート番号」(透過プロキシ用)
                \u        接続元のユーザID (番号)
                \U        接続元のユーザ名
                \g        接続元のグループID (番号)
                \G        接続元のグループ名
                        \u \U \g \G は UNIX ドメインソケットの場合のみ
                \0        SSL 証明書のシリアル番号
                \1 - \9        SSL オプションの re<n>= で指定した正規表現中、
                        ( ... ) 内の正規表現にマッチした文字列
                \?1<then>\:<else>\/
                        もし \1 (\2 - \9 も同様) の文字列が、空文字列で
                        なければ <then>、空文字列であれば <else>

        (5) は、http リクエストヘッダの先頭に <header> を追加して中継し
        ます。(4) と同様のエスケープを使うことができます。
Filed under: stone 開発日記 — hiroaki_sengoku @ 06:58
2006年4月13日

VPN-Warp 入門編

CTO日記のほうで 「VPN-Warp入門編」を始めた。 VPN-Warpというのは、port forwarder で、「relay agent」プログラムを動かしているマシンへ、「リレーサーバ」経由で TCP トンネルを掘ることができる。 つまり、イントラの中だろうが固定IPがついてない NAT の中だろうが、ダイアルアップするノートPCだろうが、インターネットへアクセスすることさえできるならば、relay agent を動かすだけで外部からアクセスできるトンネルが設置可能。

ssh の -R オプションと、-L オプションを組み合わせて同様のことが実現可能であるが、大きな違いは、ssh とちがってアカウントを作る必要がないこと。SSLクライアント証明書を発行するだけなので、異なるセキュリティポリシーのトンネルを何本でも手軽に設置できる。実際、KLab のインフラの各所で活用している。

Filed under: システム構築・運用 — hiroaki_sengoku @ 11:46
2006年4月13日

VPN-Warp 入門編 (1)

KLabセキュリティ(株)の製品に VPN-Warp という SSL VPN ソリューションがあります。 この製品は、最初のプロトタイプを私が開発し、 社内インフラ構築で長年 (といっても KLab(株) が設立からまだ 6年なので、 せいぜいそのくらいですが) 使い倒すことによって信頼性があがってきたものを、 商品化したものです。 私自身が最初に開発した、という愛着もあるので、 「仙石浩明CTO の日記」という場を利用して、 VPN-Warp を内部構造も含めて解説していきたいと思います。

VPN-Warp は、ふつうの SSL VPN に比べ、以下の特徴があります:

  1. サーバ側の設定が簡単
    特殊な設定の必要がありません。 イントラネット上の Web サーバに専用ソフトウェアをインストールするだけです。
  2. 既存のイントラネット環境を利用
    ファイアウォールの設定を変える必要がありません。
  3. PC、携帯電話、PDA などから利用可能
    主要端末に対応しています。
  4. ファイアウォール内部の情報を完璧に保護
    SSL により暗号化・認証 (クライアント・サーバ間の相互認証) で 高度なセキュリティを実現します。
  5. クライアント側への簡単な導入
    特別なソフトが必要なく SSL 証明書のインポートだけで使えます。
  6. 安定したシステム
    定評ある KLab のデータセンタを利用するため安心です。

VPN-Warp って何?

一言で言うと、ポートフォワーダです。 ssh のポートフォワードを使ったことがある人は多いと思うのですが、 基本はアレと同じです。 ssh だと、ローカルホスト (例えば自分の PC) 上で

ssh -L 8080:intra:10080 remote "sleep 1d"

などと実行することにより、 ローカルホストの 8080 番ポートを (remote から見て) intra:10080 番ポートへフォワードできます。 intra:10080 に、イントラへアクセス可能な http proxy が動いていれば、 ローカルホストの 8080 番ポートをイントラの http proxy として 使うことができるわけですね。

じゃ、ssh でいいんじゃない? なんで VPN-Warp を使うの?

ssh のポートフォワーダには大きく分けて二つの欠点があります:

  1. リモートホスト (この例では remote) にログインアカウントが必要
    ポートフォワードするためだけに、 ssh でログインできる権限を与える というのは、いかにも牛刀ですよね? また、サーバのアカウントというのは滅多矢鱈に増やせるものでもないので、 例えば数千人を超えるユーザにサービスする方法としては現実的ではありません。
  2. 外部からリモートホストへアクセスできることが必要
    この例の remote はイントラ内へアクセスできることが必要です。 イントラ内へアクセスできるサーバを 外部からアクセスできるセグメント (例えば DMZ) に置くのは 現実的ではありませんから、普通はいったん外部からアクセス可能な サーバ (例えばファイアウォール) の 適当なポート (例えば 10022 番ポート) で受けて、 それをイントラ内へフォワードするように設定しておくことになります。 DMZ に置くよりはマシであるものの、 外部から直接ログインできてしまうことにかわりはありません。

この二つの欠点は、どちらも「リモートホスト」の セキュリティレベルを下げる要因になります。 単刀直入に言えば、外部の第三者が「リモートホスト」にログインして フルコントロール権限を奪うリスクが高まっている、ということです。

次回は、VPN-Warp が上記欠点をどのように解決しているか説明します。

Filed under: システム構築・運用 — hiroaki_sengoku @ 08:06
2006年4月12日

ネットが切れる不安

ネットが切れる不安という日記を見つけた。

引っ越し先には光ファイバーが入っていないのだ(汗) 明日、ADSLが大丈夫かどうか確認して、なるべく間隔があかないように手続きをしないと。 今の時代、一日でもネットに接続できないと、なんだか不安になってしまう。

私も 6年前に引越したのだが、 ネットが切れる不安におそわれた。 なんとか間隔があかないように苦労したのを覚えている。 顛末は日経Linuxの連載の枕 (PDF版) に書いた。

引っ越し作業中も社宅でサーバーを動かし続ける必要があるわけですが,部屋中に電話線やらEthernetケーブルが張り巡らせてある状態で引っ越し作業ができるはずはないので,サーバー,ルーター,TA(Terminal Adapter),電話等のネットワーク関係を部屋の片隅の半畳程度の部分に再構築し,作業中絶対にこの部分には近付かないよう*3 引っ越し業者の方にお願いすることにしました

当時はまだ ADSL のサービスが始まっていなかったので、OCN エコノミーを利用していた。だから TA。

Filed under: システム構築・運用 — hiroaki_sengoku @ 20:01
2006年4月11日

情報処理のキホン (1) hatena_b

KLab の開発に参加いただいている協力会社の A 社の S 社長が、

- o -

私自身は情報処理のキホンをちゃんと「教わったり習ったり」した ことはなく、その点で、至る所で「やっぱりキホンがしっかりして いる人には適わないなぁ」と感じるシーンも経験します。

で、大学や専門学校で情報処理を学んで来た人に教えて欲しいの ですが・・・・・・

Q1) 学校でどんなコース(講義/単位)がありましたか。
○○学 とか ○○技法 とかそんな感じの。
Q2) その中で、印象深かったものや、今こうやって開発の現場で仕事を
していて「学んでよかったなぁ」と思ったものを教えてください。
Q3) 今この会社の、学校でそういうことを学んでこなかった人に対して
「俺が解るように教えてやる!」というのがあるとしたら
どんな事ですか。
- o -

という質問を tech ML にしました。
みなさんならどう答えますか?

A1)
私は情報工学科だったので、論理回路からコンパイラ、ソフトウェア工学まで一 通り学びました。ついでにいうと実践的なプログラミングは、某ソフトウェアハ ウスでバイトして覚え、ネットワークは、最初の就職先のイントラ構築の手伝い をして覚えました。
A2)
専門課程で学ぶ事で一番大事なのは、「大海」を知る事ですね、きっと。 「大海」を知らない「井の中の蛙」は、決して「井」から出る事はできません。
大事なのは知識や経験を身につける事ではなくて、自分が何を知らないかを 知る事です。
大学は「開発の現場で」役にたつことを教えてくれない、と多くの人が言います が、そういうことを言う人って、ほぼ確実に自分が何を知らないか分かってない と思います。
A3)
なんでもいいです。自分では到底作り出す事ができないものについて、 完全に理解するよう努力する経験をすることができるのであれば。
言い替えれば、何か (What) を学ぶ事が重要なのではなくて、
まして、どうやって (How) を覚える事なんて重要であるはずがなく、
体得すべきは、なぜ (Why) を問い続ける習慣そのものです。

「トランザクション輪読会」(社内輪読会です) の本を、 「分かったつもり」レベルではなく、 完全に理解できるまで頑張るとかでも、もちろんいいですね。 どこまで完全に理解できたか自体は、実はあまり重要ではなくて、 理解しようと努力して、自身の限界まで力を出し切ってみることが事が 大事なのではないかと。

「輪読会」に参加した人は実感していると思いますが、何が分からないか 分からない人は、質問さえできないわけです。自分が本当に理解できているか、 常に反省する習慣を身に付けたいものです。

ちなみに私は大学生の時、隣の理学部の数学科へ出かけていって、 なんとか理解しようとさんざん苦しんだ挙げ句、 どーしても「分かったつもり」レベルから脱することができずに 自身の理解力の限界を知る経験をしました。

いちおーその単位は取ったのですが、数学者になることはあきらめて 情報工学に専念しようと思ったのでした。

Filed under: 技術と経営 — hiroaki_sengoku @ 07:17
2006年4月11日

同時に考えよう (2)

同時に考えよう」で無意識の思考について私自身の経験について述べたのであるが、驚いたことにそういう仮説が実際にあって、実験も行われているらしい。

Don't think too much, It's allright」(医学都市伝説)で紹介されている論文によると、

多くの判断要素のある事柄の選択については、無意識的思考が勝るという作業仮説から研究を行った。仮説は「集中なき熟考」と名付けられ、それを元に消費選択についての四つの実験が行われた。これらは実験室だけでなく、街角の商店でも行われ、複雑な判断要素のある商品購入の際には、意識を集中させた熟考によって、かえって悪い結果を得られることが確かめられた」。

だそうだ。この仮説が「都市伝説」なのかどうかよくわからない (^^;) が、

著者たちはこれらの結果から、どこに住み、どんな仕事をするかというような、多くの判断基準が錯綜する事柄について選択をする場合、それらの条件をいったん胸に納め、それに集中することなく「無意識下」で暖めておくことが、もっともよい決断結果が得る道だと主張している。

という主張は、私の感覚ととてもよくマッチする。判断基準から選択を行う思考の場合だけでなく、初めて見る数学の問題を解くとか、さらには全く新しいアイディアを思いつく、などといったような創造的な思考をも無意識下に行える、と私としては主張したいところであるが、実験で「創造的な思考を行えたか」検証するのは難しそうだ。

Filed under: 自己啓発 — hiroaki_sengoku @ 06:44
2006年4月10日

守秘義務

取引先が秘密保持契約(NDA)のもと開示した秘密や、お客様のデータや、経営情報などについては、あからさまに「秘密」という感じがするので、それが守秘義務の範囲に含まれることは誰の目にも明らかだろう。では、ノウハウはどうだろうか?

本当に件のノウハウなんか「しゃべるな」と言われたから(=明確に秘するべき事と定義されたから)言わないだけで、別にそれを知ったからといってPerl のディストリビューションができるわけでも、俺もディストリビューションを作ってやろうと思わせるもんでもないし、マジで「コロンブスの卵」のノウハウ程度のもの。 (秘密にすべきことは明確にされるべき)

なにを「秘するべき事と定義」するかは各社の考え次第だから、私がとやかく言うことではないが、少なくとも弊社では、アイディア自体は秘密とは考えない。

ベンチャー起業の鉄則
アイデアなんて二束三文だ
(ベンチャー起業の秘訣!無料アイデア付き)

と社長自らが言っているし、 私も以前考案したDB サーバのセキュリティ向上策をはじめとして、 実地の運用ノウハウを公開していきたいと思っている。 「アイデアは人に話すことで熟成していく」 (ベンチャー起業の秘訣!無料アイデア付き)と考えるからだ。

そもそもノウハウは、アイディア自体にあるのではなく、 そのアイディアを具現化できる「人」にこそあるのだと思う。

Filed under: 技術と経営 — hiroaki_sengoku @ 07:38
« Newer PostsOlder Posts »