離れたところからGrowlで通知 - UDPのパケットをSSHでポートフォワードする方法

  • Growlに、LANの外のマシンから通知リクエストを投げたい。
  • Growlは、リモートから通知リクエストを受ける機能がある。
    • UDPの9887番ポートを使用
  • が、Growlが動いているマシンと通知リクエストを行うマシンは、それぞれ異なるLANに属していて、直接通信できない。
  • そんなときお手軽便利なのは、SSHのポートフォワード。これでずるっとトンネルを開通すればいい。
  • が、TCPのパケットしかポートフォワードできない。

というわけで、

な構成にすればOK

が、Mac (Mac OS X 10.4.10, Intel) だと stone (2.3d) のUDP/TCP変換がうまく動かない —もうちょっと具体的にいうと、sendtoがエラーリターンする(調査中…)—

TCP5>UDP6: sendto failed err=56: to 127.0.0.1:9889/udp

56 EISCONN Socket is already connected. A connect request was made on an already connected socket; or, a sendto or sendmsg request on a connected socket specified a destination when already connected.

http://developer.apple.com/documentation/Darwin/Reference/ManPages/man2/intro.2.html

ので、Growlなマシンと同じLAN内にあるLinuxマシンでTCPUDPの変換をしました。

図にするとこんな感じ。

┏━━━━━━━━━━━━━━━━━
┃┌[notifier]───────────
┃│Net::Growl
┃│↓
┃│localhost:9887/udp
┃│  stone // stone -nr localhost:9888 localhost:9887/udp
┃│↓
┃│localhost:9888/tcp
┃│  ssh   // ssh -L 9888:localhost:9888 relay
┃└────────────────
┗━━━━━━━━━━━━━━━━━
  ↓
〜〜〜
  ↓
┏━━━━━━━━━━━━━━━━━
┃┌[relay ]────────────
┃│localhost:9888/tcp
┃│  stone // stone -nr growl:9887/udp localhost:9888
┃└────────────────
┃  ↓
┃┌[growl ]────────────
┃│*:9887/udp
┃│  Growl
┃└────────────────
┗━━━━━━━━━━━━━━━━━

追記 2007-10-22 14:05

Mac (Mac OS X 10.4.10, Intel)とFreeBSD 6.2で、

stone-2.3d
本文と同じく、EISCONNが発生。
stone.c 2.3.2.2
正常に通信成功。

を確認しました。対応ありがとうございました!> id:gcd san

また、『UNIXネットワークプログラミング〈Vol.1〉ネットワークAPI:ソケットとXTI』の「8.11 UDPにおけるconnect関数」(p.216) に関連する記述がありました。
要約すると、接続済みUDPソケット(connectしたもの)に対して終点指定ありのsendtoを行った場合の結果は以下のようになるそうです。

環境 結果
4.4BSD EISCONN
Posix.1g EISCONN
Solaris 2.5 OK
Linux 2.6 OK (これは私の実験の結果から)