Linux で、TCP 接続に (というか IP パケットに) 何も手を加えずただ指定のアドレスに中継・橋渡しするだけのプロキシを作る方法について、楽な方法は何があるでしょうか?


iptables で DNAT と MASQUERADE を組み合わせればできるかなと思い、試しに
iptables -t nat -A PREROUTING -p tcp -d (自分のIP) -j DNAT --to (転送したい宛先アドレス)
iptables -t nat -A POSTROUTING -p tcp -d (転送したい宛先アドレス) -j MASQUERADE
としてみましたが、期待通りに働きませんでした。(クライアントから接続をかけようとするとタイムアウトする)

iptables の使い方が間違っているでしょうか? それとも iptables では不可能で、簡単なデーモンを用意しないと無理でしょうか? その場合、そのような汎用中継デーモンは既に何か存在するでしょうか?
お知恵を貸していただけると助かります。

回答の条件
  • 1人5回まで
  • 登録:
  • 終了:2010/01/08 01:59:04
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

ベストアンサー

id:JULY No.3

回答回数966ベストアンサー獲得回数247

ポイント35pt

naruenosekai さんが紹介しているのは Delegate の TCPrelay や UDPrelay を使う方法で、この場合は、任意のプロトコルで中継が出来ます。同様の事は、socat でも出来ます。socat を xinetd から呼び出すようにして、

service サービス名(/etc/services に書かれている名称)
{
        disable = no
        socket_type     = stream
        wait            = no
        user            = root
        server          = /usr/bin/socat
        server_args     = stdin tcp4:宛先のホスト:ポート番号
}

といった具合のファイルを /etc/xinetd.d 以下に作ります。もし、お使いのディストリビューションが、RHEL や CentOS だった場合、socat 自体は rpmforge から取得出来ます。

ただ、Delegate の場合でも socat の場合でも、「このポートに届いたものは中継」ということになるので、任意のポートで、とはいきません。

あと、そもそもパケットのペイロード部分にアドレス情報が入るようなプロトコル(たしか、SIP 関係とか、IPsec 当たりがそうだった気がする)だった場合、ペイロードに入っているアドレス情報とIP ヘッダのアドレス情報に矛盾が発生するとダメというケースもあるので、どんなプロトコルでも、というのは難しいです。

試されている iptables の方法も、何かを加えれば出来そうな気がするのですが、wireshark とかでパケットキャプチャして、実際にどんなパケットが飛び交っているのかを確認すると、解決策が見つかるかもしれません。

id:pmakino

socat はまさに私が求めていたものです! ありがとうございます!

> そもそもパケットのペイロード部分にアドレス情報が入るようなプロトコル…

そうですね。そのようなものは仕方ないと思います。

2010/01/06 19:10:43

その他の回答2件)

id:naruenosekai No.1

回答回数140ベストアンサー獲得回数12

ポイント25pt

マルチプロトコルプロキシーのDeleGateを使うと楽に出来ます。

http://ja.wikipedia.org/wiki/DeleGate

http://www.delegate.org/delegate/

設定方法

http://i-red.info/docs/JF/delegate-mini-howto.html

http://i-red.info/docs/JF/delegate-mini-howto-config.html

http://pyzarlab.s101.xrea.com/delegate/details.html

http://homepage1.nifty.com/yito/anhttpd/faq/delegate.html

あと中継する場合、送信元のIPアドレスやMACアドレスを中継するPCに変更、戻ってきたパケットは逆変換しないと

正しく中継できないと思いますが...

id:pmakino

> マルチプロトコルプロキシーのDeleGateを使うと楽に出来ます。

なるほど、ありがとうございます。

サポートされているプロトコルなら間違いなくそれでいけそうですが、

もしかして DeleGate はサポートされていないプロトコルでもいけるでしょうか?

(例えば VNC や ssh といったものを中継したい、という場合など)

> あと中継する場合、送信元のIPアドレスやMACアドレスを中継するPCに変更、戻ってきたパケットは逆変換しないと正しく中継できないと思いますが...

はい、その通りなのです。

なので単なる DNAT だけではダメで、SNAT を組み合わせようとしたのですが、うまくいかなったという次第です。

2010/01/06 01:35:35
id:yoshifumi1975 No.2

回答回数58ベストアンサー獲得回数10

ポイント20pt

sshのポートフォワーディングを使えばプロトコルに関係なく、プロキシーできます。

接続元のPC -- 中継Linux -- 目的サーバー

という状態の場合、ポートがTCPの1234番だった場合

接続元PCから、

ssh -N -g -L 1234:目的サーバーのIP:1234 ユーザ名@中継Linux

と実行すると、接続元PCの1234に接続すると、中継Linuxを介して、目的サーバーの1234番に接続できます。

中継Linuxから、

ssh -N -g -L 1234:localhost:1234 ユーザ名@目的サーバー

と実行すると、中継Linuxの1234に接続すると、目的サーバーの1234番に接続できます。

これを使えば、外出先から、自宅のLinuxを介して自宅LAN内のWindowsにVNCで接続もできます。

アイデア次第でいろいろ遊べると思います。


http://d.hatena.ne.jp/yoshifumi1975/20060330/1143704653

id:pmakino

なるほど、そのような手もありますね。ありがとうございます。

2010/01/06 19:07:38
id:JULY No.3

回答回数966ベストアンサー獲得回数247ここでベストアンサー

ポイント35pt

naruenosekai さんが紹介しているのは Delegate の TCPrelay や UDPrelay を使う方法で、この場合は、任意のプロトコルで中継が出来ます。同様の事は、socat でも出来ます。socat を xinetd から呼び出すようにして、

service サービス名(/etc/services に書かれている名称)
{
        disable = no
        socket_type     = stream
        wait            = no
        user            = root
        server          = /usr/bin/socat
        server_args     = stdin tcp4:宛先のホスト:ポート番号
}

といった具合のファイルを /etc/xinetd.d 以下に作ります。もし、お使いのディストリビューションが、RHEL や CentOS だった場合、socat 自体は rpmforge から取得出来ます。

ただ、Delegate の場合でも socat の場合でも、「このポートに届いたものは中継」ということになるので、任意のポートで、とはいきません。

あと、そもそもパケットのペイロード部分にアドレス情報が入るようなプロトコル(たしか、SIP 関係とか、IPsec 当たりがそうだった気がする)だった場合、ペイロードに入っているアドレス情報とIP ヘッダのアドレス情報に矛盾が発生するとダメというケースもあるので、どんなプロトコルでも、というのは難しいです。

試されている iptables の方法も、何かを加えれば出来そうな気がするのですが、wireshark とかでパケットキャプチャして、実際にどんなパケットが飛び交っているのかを確認すると、解決策が見つかるかもしれません。

id:pmakino

socat はまさに私が求めていたものです! ありがとうございます!

> そもそもパケットのペイロード部分にアドレス情報が入るようなプロトコル…

そうですね。そのようなものは仕方ないと思います。

2010/01/06 19:10:43

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません