コマンドラインから簡単にUDP通信を行うには

Linux/MacなどでコマンドラインからTCP通信を行うには、telnetがよく使われますね。

HTTPアクセスをtelnetで行う例:

telnet example.com 80
GET / HTTP/1.1(改行)
Host: example.com(改行)
Connection: close(改行)
(空行)
HTTP 200 OK
Content-Type: text/html
... 以下略

UDPでTCPと同じようにテキストベースの通信を行うには、netcat(ncコマンド)が便利です。
netcatはtelnetの機能拡張版ともいえるツールで、TCP/UDPプロトコルを扱う上ではぜひ導入しておきたいものです。

nc コマンドが手元にインストールされてない場合、

CentOS系Linuxなら sudo yum install netcat

Debian なら sudo apt-get install netcat

OS X(Homebrew)なら brew install netcat

でインストールできるかと思います。

netcatは基本的にはtelnetと同じ使い方ができます。

使い方:

netcat -u 接続先IPまたはホスト名 ポート

-u はUDP通信を表すオプションで、省略するとデフォルトでTCP通信になります。
telnet同様、パイプなしで実行すると、標準入力待ち状態になり、Ctrl-Cで切断できます。

また、telnetと違い、サーバになることもできます。

netcat -l -u -p port

-l は Listenモード(サーバモード)、
-u はudpプロトコルでの待受を意味します。(省略するとTCPプロトコル)
-p は待ち受けるポート番号です。

簡易通信サーバになって接続をテストすることも可能です。便利ですね。

もちろん、サーバ・クライアント両方ともncでも通信できます。

サーバ側コンソール(ローカル):

$ nc -l -p 55440 # 適当なTCPポート55440で待受(udpでもOK)

クライアント側コンソール(ローカル):

$ nc localhost 55440 # サーバにつなぐ。(TCPならtelnetでもOK)
hogehoge(改行)

こうすると、サーバ側コンソールに hogehoge と表示されます。
逆にサーバ→クライアントにメッセージを送ることも可能です。

また、上記の例では同一ホストで実行していますが、もちろんIPアドレス、ドメイン指定などで別マシンとも通信できます。

ローカルでやると動くのに、別マシンにはつながらない、という場合はファイアウォールを確認するとだいたい解決するかと思います。
終了できない!と焦ったら、Ctrl-Cを推してみましょう。

ぜひご自身で色々試してみて下さい!

[Linux] ping された事を検知する(tcpdump)

ネットワーク到達確認をするときにpingをうちますが、
自分が本当にpingを受け取ったのか確認したい事もたまにあります。

こんな時、pingされたことを検知するには、tcpdumpを使うと便利です。

> sudo tcpdump ‘icmp[0] = 8’

############ 監視サーバ側 ############## 
% sudo tcpdump 'icmp[0] = 8'     
[sudo] password for user: 
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
(監視状態に入る)

ここで監視サーバにpingが来ると監視サーバには以下のようにログが流れます。

17:35:23.241574 IP xxx.xxx.xxx.xxx > example.com: ICMP echo request, id 13727, seq 0, length 64
17:35:24.241852 IP xxx.xxx.xxx.xxx > example.com: ICMP echo request, id 13727, seq 1, length 64

xxx.xxx.xxx.xxxは実際にはping元のIPアドレス(またはホスト)、example.comはping先(監視サーバ)のIPアドレス(またはホスト)になります。

終了するときは Ctrl-C で終了します。

Mac OS X でポートを開いているプログラムを調べる

WindowsやLinuxでは netstat の -bオプションや-pオプションでポートを待ち受けているプロセスを調べる事ができるのに、Mac OS Xではそんなオプションが無く困った。

なんとか方法が他にないか調べた所、
Mac OS X では lsof を使うのが一番簡単そう。

$ lsof -i | grep LISTEN

結果はこんな感じになる。

$ lsof -i | grep LISTEN
Dropbox     303   user   19u  IPv4 0xffffff0123456789      0t0  TCP *:17500 (LISTEN)
Dropbox     303   user   25u  IPv4 0xffffff0123456789      0t0  TCP localhost:26165 (LISTEN)
node      56728   user    8u  IPv4 0xffffff0123456789      0t0  TCP *:hbci (LISTEN)
mongod    57071   user    6u  IPv4 0xffffff0123456789      0t0  TCP localhost:28017 (LISTEN)
mongod    57071   user    7u  IPv4 0xffffff0123456789      0t0  TCP localhost:27017 (LISTEN)

調べようと思った動機は mongodb のListenポートをど忘れして確認したかっただけでした。
実行結果を見ると mongodb は TCP localhost:27017, TCP localhost:28017とあるので、
待ち受けているポートはTCPポート27017, 28017の2つですね。

Android – HttpClient のクッキー管理機能をカスタマイズする

HttpClient のクッキー処理の仕様をブラウザに合わせたい、RFC準拠にしたい、自分で管理したい、という時はクッキーポリシーの設定で動作を変更することができます。
方法1: 標準で提供されているクッキーポリシーを選んで設定する
例:

DefaultHttpClient client = new DefaultHttpClient(params);
client.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.NETSCAPE); // SetCookieの扱いをNetscapeの仕様に変更

 
設定可能な値:
– CookiePolicy.BEST_MATCH … デフォルトのベストマッチポリシー
– CookiePolicy.RFC_2109 … RFC2109に準拠(時代遅れの厳密なポリシー)
– CookiePolicy.RFC_2965 … RFC2965に準拠(標準的で厳密なポリシー)
– CookiePolicy.NETSCAPE … ネットスケープのドラフトに準拠
– CookiePolicy.BROWSER_COMPATIBILITY … (おかしな)一般的なブラウザと互換性がある動作にする。
 
方法2:カスタムポリシーを使う
例:

DefaultHttpClient client = new DefaultHttpClient(params);
// カスタムクッキーポリシーを定義する
CookieSpecFactory csf = new CookieSpecFactory() {
 
@Override
public CookieSpec newInstance(HttpParams params) {
return new BrowserCompatSpec(){
@Override
public void validate(Cookie cookie, CookieOrigin origin)
throws MalformedCookieException {
// ここで判定してクッキー導入処理を行う。
// super.validate(cookie, origin);
}
};
}
};
client.getCookieSpecs().register(“myspec”, csf); // カスタムポリシーに結びつけるキーワードを登録して・・
client.getParams().setParameter(
ClientPNames.COOKIE_POLICY, “myspec”); // そのキーワードでポリシーを設定!

 
カスタムポリシーを定義する場合は標準で提供されているポリシーのソースが参考になります。
 
– RFC_2109 … RFC2109Spec.java
– RFC_2965 … RFC2965Spec.java
– NETSCAPE .. NetscapeDraftSpec.java
– BROWSER_COMPATIBLE .. CookieSpecBase.java
 
その他クッキー関係の設定方法は公式ドキュメントに詳しく書かれています。
 
参考:
HttpClientでのCookieの扱い(HttpClient3.0-rc3)
HttpComponentsライブラリ公式ドキュメント(hc.apache.org)
RFC2109(日本語訳)
RFC2965(日本語訳)
HttpComponentsのcookieパッケージソース(svn.apache.org)

HTTP – Locationヘッダには相対URLを使ってはいけない

HTTP の仕様(RFC2616)では、 Location ヘッダは絶対URIでなければならないと今更知りました。
Hypertext Transfer Protocol — HTTP/1.1(日本語) 14.30:

Location = “Location” “:” absoluteURI

ちなみに絶対URI(absolute URI)とはRFC2396によるとスキームから始まるURIのみを指します。
スラッシュ(“/”)から始まる URL が絶対URLと言われることがありますが、正確には絶対パス(absolute path)指定の相対URLであり、絶対URLではありません。

absoluteURI = scheme “:” ( hier_part | opaque_part )
hier_part = ( net_path | abs_path ) [ “?” query ]
relativeURI = ( net_path | abs_path | rel_path ) [ “?” query ]
net_path = “//” authority [ abs_path ]
abs_path = “/” path_segments

 
ただ、ほとんどのブラウザで相対URLへのロケーションを寛容に解釈してくれます。
lynx では警告が出るようですが、一般向けには携帯でさえ(mova など余程古いものを除けば)意図通りにリダイレクトしてくれるようになり、仕様違いでも問題がほぼなくなってしまいました。
 
相対URLが便利なのも事実。なのでもしかしたら HTTP 2.0 ができるときには相対URI可、なんてことになるかもしれませんね。

インターネットにつながずに2台のマシンを無線通信する

無線LANでピアツーピア接続(アドホックモード)する方法(東芝 dynabook サポート)
XP/Vista なら標準でアドホック(P2P)接続できるのですね。
 
参考:
無線 LAN を使いこなしてトクする Windows XP – パソコン同士でつなぐ(Microsoft At Home マガジン)
 
WiPeer
XP/Vista 用のP2Pメッセンジャー。ファイル共有機能つきで、通信の暗号化アルゴリズムはWEPのみ。
 
アドホックで無線通信を可能にする『WiPeer』

任意のデータを表現するURL

RFC 2397 に規定される data:// から始まる URL を利用すると、任意のデータを URL として表現できます。

書式:
“data://” [MIME] [“;base64”] “,” data

たとえば

<a href=”http://www.ecoop.net/”>hello!</a>

という HTML テキストは data スキームを使うと以下のようになります。

data://text/html,%3Ca+href%3D%22http%3A%2F%2Fwww.ecoop.net%2F%22%3Ehello%21%3C%2Fa%3

また、base64 形式でも指定できます。

data://text/html;base64,PGEgaHJlZj0iaHR0cDovL3d3dy5lY29vcC5uZXQvIj5oZWxsbyE8L2E+

 
IMG タグのソースURLとして利用する例(RFC2397より引用)

   <IMG
   SRC=”data:image/gif;base64,R0lGODdhMAAwAPAAAAAAAP///ywAAAAAMAAw
   AAAC8IyPqcvt3wCcDkiLc7C0qwyGHhSWpjQu5yqmCYsapyuvUUlvONmOZtfzgFz
   ByTB10QgxOR0TqBQejhRNzOfkVJ+5YiUqrXF5Y5lKh/DeuNcP5yLWGsEbtLiOSp
   a/TPg7JpJHxyendzWTBfX0cxOnKPjgBzi4diinWGdkF8kjdfnycQZXZeYGejmJl
   ZeGl9i2icVqaNVailT6F5iJ90m6mvuTS4OK05M0vDk0Q4XUtwvKOzrcd3iq9uis
   F81M1OIcR7lEewwcLp7tuNNkM3uNna3F2JQFo97Vriy/Xl4/f1cf5VWzXyym7PH
   hhx4dbgYKAAA7″
   ALT=”Larry”>

テキストファイルだけでなく画像データや音声データなど、任意のデータファイルを表現することができます。ただし A タグのHREF属性で利用する場合など利用環境によって URIの文字列長制限がある場合もあるため、比較的小さいデータを表現するときに利用するのがいいでしょう。
 
参考:
RFC 2397 The “data” URL scheme

UDP Hole Punching の実験

以前から気になっていた、NAT ごしに UDP 通信を行う, UDP Hole Punching の実験を NetCat(ports: net/netcat) を使って行ってみました。
 
1. (A)ホスト側端末(Firewall なし), WAN IP アドレス: 10.0.1.2

nc -lup 1234 -v # UDP の 1234 番で LISTEN

 
2. (B)クライアント側端末(ルータあり), 端末の IP アドレス: 192.168.1.100, ルータの WAN IP アドレス: 10.0.5.6

nc -u -p 5678 10.0.1.2 1234 # 10.0.1.2 の UDP 1234 に接続

 
3. (B) で Hello を入力
 
4. (A) に以下のようなログが出る

connect to [10.0.1.2] from ********* [10.0.5.6] 50000
Hello

(この例では 10.0.5.6 の UDP50000ポートからの送信があった。クライアント側 NAT で送信元ポートが書きかわっている事に注意)
 
5. (A), (B) 両方で netcat を一度終了させる
 
6. (B) で, 先程送信元にしたポートに対して UDP 受信を開始する(src port, dst port の入れ換え)

nc -lup 5678 -v

 
7. (A) で, 先程 LISTEN していたポートから、(4) で送信元になっていた IP アドレス、ポートに対して接続を開始する

nc -u -p 1234 10.0.5.6 50000

 
8. (A) から Hello over NAT を送信
 
9. (B) で以下のようなログが表示される

connect to [192.168.1.100] from ********* [10.0.1.2] 1234
Hello over NAT

 
両方が NAT 内にいる場合、双方について source port が書きかわるため、(A),(B) が通信することが不可能になります。
この場合、双方の source port を記録するための非 NAT 内ホスト端末 (C) が必要です。
ただし、双方が Symmetric NAT 内にいる場合は、宛先のポート番号に対して送信元の IP アドレス、ポート番号が固定されるためこの方法を用いることができません。
 
参考:
P2Pとファイアウォール
ごろ猫ブログ
みかログ
IT media エンタープライズ:PART2 Skype, その通信の仕組み

bind で設定が反映されない場合の原因と対策

– named.conf の場所が違う, または権限が不足している
  named の起動オプションで

named -c /etc/named/named.conf

   のように -c で設定ファイルへのパスを指定してみましょう。
 
– 名前解決で自分を見ていない
  > nslookup example.com 127.0.0.1
  または
  > dig @127.0.0.1 example.com
  でDNSサーバを明示してみます。
  これで解決できるなら、解決先が正しくない可能性が高いです。
  たとえば UNIX 系なら /etc/resolv.conf で
  > nameserver 127.0.0.1
  のように解決先を指定していない可能性があります。
 
– 設定ファイルの文法が間違っている
  文法が間違っていると、黙ってその設定ファイルを無視します。
named.conf と zone ファイルの文法を次のコマンドでチェックしてみましょう。

named-checkconf <named.conf のパス>
named-checkzone <ゾーン名> <ゾーンファイルのパス>

 
具体的にはたとえば次のようにします。

named-checkconf /etc/named/named.conf
named-checkzone example.com /etc/named/example.com.zone

これを実行し、named-checkconf の場合何も表示されなければ、named-checkzone の場合最後に OK と出れば、そのファイルの文法は正しいということです。
 
文法が間違っている場合、エラーメッセージが出力されるので、それを元に正します。
 
– 設定ファイルの変更後、DNS をリロード/再起動していない
  設定ファイルは、リロードまたは再起動しないと即時反映されません。
  > /sbin/named.reload
  などとして、明示的にリロードすることで直ちに反映されます。
 
参考:
@IT:実用 BIND 9 で作る DNS サーバ

Ethereal,Tethereal が FreeBSD の ports から消えてた

ローカルの ports で探してみて、net/ethereal にあったはずの Ethereal が見付からなくてアレッ!?と思って公式の cvsweb をあたって見たところ
次のように書いてました。
 
http://www.jp.freebsd.org/cgi/cvsweb.cgi/ports/net/ethereal/Attic/Makefile?hideattic=0

FILE REMOVED
 
Add wireshark and tshark after repocopies from ethereal and tethereal
respectively. Wireshark is a rename of ethereal after the principal
developer moved companies and lost the Ethereal copyright.
 
Messenger, don’t shoot!
 
Now the ethereal binary is called wireshark, the tethereal binary is
called tshark, and idl2eth is now idl2wrs. All other binaries have
kept the same name.
 
In addition to this name change, I have also changed the PREFIX from X11BASE
to LOCALBASE.

 
Ethereal(CUI 版: TEthereal) は主要な開発者が会社を辞めて商標権を失って wireshark(CUI 版: tshark) という別の名前で存続する事になった、ということです。
 
ということで ports を改めて見ると、 net/wireshark, net/wireshark-lite, net/tshark, net/tshark-lite が増えてました。
 
Wireshark の公式サイトは http://wireshark.org/ で、
現在、Ethereal 0.99 から更新された Wireshark 0.99.2 がリリースされています。
 
参考:
「Ethereal」は「Wireshark」に飲み込まれるのか?(ITpro)
Wireshark 公式サイト
Ethereal 公式サイト