iptables-パケットを特定のインターフェースにルーティングするターゲット?


25

私のホームサーバーには、2つの主要なインターフェイスeth1(標準的なインターネット接続)とtun0(OpenVPNトンネル)があります。私はiptablesUID 1002が所有するローカルプロセスによって生成されたすべてのパケットを強制的に通過しtun0、他のすべてのパケットを通過して終了したいと思いますeth1

一致したパケットを簡単にマークできます。

iptables -A OUTPUT -m owner --uid-owner 1002 -j MARK --set-mark 11

ここで、11でマークtun0されたパケットと一致するルールをPOSTROUTINGチェーン(おそらくマングルテーブル)に入れて送信し、その後、すべてのパケットと一致するルールを送信しますeth1

ROUTEターゲットを見つけましたが、それはソースインターフェイスを書き換えているだけのようです(間違って読んでいない限り)。

iptablesはこれに対応していますか?代わりに、ルーティングテーブルを(ip routeまたは従来のrouteコマンドだけで)混乱させる必要がありますか?

編集:多分もっと情報を提供すべきだと思った。現在、他のiptablesルールはありません(将来、無関係のタスクを実行するためにいくつかのルールを作成する可能性があります)。また、の出力ip routeは次のとおりです。

default via 192.168.1.254 dev eth1  metric 203
10.32.0.49 dev tun0  proto kernel  scope link  src 10.32.0.50
85.17.27.71 via 192.168.1.254 dev eth1
192.168.1.0/24 dev eth1  proto kernel  scope link  src 192.168.1.73  metric 203

ルーティングテーブルには触れていません-これは現在の状態です(かなり汚れているように見えますが)。申し訳ありませんが、routeこのマシンにはレガシーコマンドがインストールされていません。

そして、出力ip addr(もちろん、eth0とeth2は無視できます-現在使用されていないNICです):

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 1000
    link/ether 1c:6f:65:2a:73:3f brd ff:ff:ff:ff:ff:ff
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast     state UP qlen 1000
    link/ether 00:1b:21:9d:4e:bb brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.73/24 brd 192.168.1.255 scope global eth1
    inet6 fe80::21b:21ff:fe9d:4ebb/64 scope link
       valid_lft forever preferred_lft forever
4: eth2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 1000
    link/ether 00:1b:21:6a:c0:4b brd ff:ff:ff:ff:ff:ff
5: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc     pfifo_fast state UNKNOWN qlen 100
    link/none
    inet 10.32.0.50 peer 10.32.0.49/32 scope global tun0

編集:なんらかの機能が得られましたが、マークされたパケットをtun0に転送していません。基本的に、テーブル(11)を追加して使用しました。

ip route add table 11 via 10.32.0.49 dev tun0
ip rule add priority 10000 fwmark 11 table 11

ちょうどのときsudo -u user1000 wget -qO- whatismyip.org、自宅の外部IPアドレスを取得しますが、取得した場合sudo -u user1002 wget -qO- whatismyip.org、自宅のIPアドレスも取得します(ただし、OpenVPNトンネルの反対側でIPを取得する必要があります)。

実行iptables -vLにより、パケットがマーキングルールと一致することが確認されますが、ルーティングルールに従っていないように見えます。

編集:私はこれに長い時間を費やし、それでもまだ動作しませんが、私は少し近いと思います。

iptablesルールは、mangleテーブルのOUTPUTチェーンに含まれている必要があります。natソースアドレスを設定するには、テーブルのPOSTROUTINGチェーンにMASQUERADEルールも必要だと思います。ただし、OUTPUTのマングルの後に発生する再ルーティングは正しく機能していません。

私は今これに5時間を費やしているので、休憩を取っており、おそらく今夜遅くに、または明日いつかに戻るでしょう。

回答:


26

私は最近、同様の問題に直面しましたが、わずかに異なります。私はルートに望んでいただけで、デフォルトのインターフェイスを介して(でも、同じホストのための)他のすべてのトラフィックをルーティングしながら、のOpenVPN TAP0インタフェース上でTCPポート25(SMTP)。

そのためには、パケットをマークし、それを処理するためのルールを設定する必要がありました。まず、2スルーテーブルでマークされたパケットをカーネルにルーティングさせるルールを追加します3(後で説明します)。

ip rule add fwmark 2 table 3

にシンボリック名を追加することもできます/etc/iproute2/rt_tablesが、そうすることはありません。番号23はランダムに選択されます。実際、これらは同じ場合がありますが、明確にするために、この例では行いませんでした(ただし、自分のセットアップで行いました)。

ゲートウェイを次のように想定して、トラフィックを別のインターフェイスにリダイレクトするためのルートを追加します10.0.0.1

ip route add default via 10.0.0.1 table 3

非常に重要です!ルーティングキャッシュをフラッシュします。そうしないと、応答が得られず、数時間髪に手を触れたままになりません。

ip route flush cache

次に、指定されたパケットをマークするためのファイアウォールルールを設定します。

iptables -t mangle -A OUTPUT -p tcp --dport 465 -j MARK --set-mark 2

上記のルールは、パケットがローカルマシンから送信された場合にのみ適用されます。http://inai.de/images/nf-packet-flow.pngを参照してください。要件に合わせて調整してください。たとえば、tap0インターフェイスを介して発信HTTPトラフィックのみをルーティングする場合は、465を80に変更します。

送信tap0元IPと​​してLANアドレスを取得して送信されるパケットを防ぐには、次のルールを使用して、それをインターフェイスアドレスに変更します(インターフェイスの10.0.0.2IPアドレスと仮定tap0):

iptables -t nat -A POSTROUTING -o tap0 -j SNAT --to-source 10.0.0.2

最後に、リバースパスのソース検証を緩和します。いくつかは、あなたがそれを設定することをお勧めし0ますが、2に応じてより良い選択と思われるhttps://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt。これをスキップすると、パケットを受信します(これはを使用して確認できますtcpdump -i tap0 -n)が、パケットは受け入れられません。パケットが受け入れられるように設定を変更するコマンド:

sysctl -w net.ipv4.conf.tap0.rp_filter=2

なぜマスケレードの代わりにSNATを使用するのですか?IPアドレスが「実行時」にインターフェースから収集され、構成ファイルにハードコーディングされていないことを除いて、MASQUERADEは同じことをしませんか?
イーサン

6
@Ethan From man iptables動的に割り当てられたIP(ダイヤルアップ)接続でのみ使用する必要があります。静的IPアドレスがある場合は、SNATターゲットを使用する必要があります。マスカレードは、パケットが送信されるインターフェイスのIPアドレスへのマッピングを指定することと同等ですが、インターフェイスがダウンすると接続が忘れられるという効果もあります。あなたは正しいですが、私のIPは決して変わらないので、マンページの推奨ごとにSNATを使用することにしました。
-Lekensteyn

(テストはされていませんが)最後のステップ(リバースパスソースの検証)は必要ないと思います。PREROUTINGチェーンに別のルールをDNAT正しい送信元アドレスに追加するだけです(デフォルトゲートウェイに従って)。
クリスチャンウルフ

7

これを解決しました。問題は表11のルーティングルールにありました。表11 ヒットしていましたが、ルーティングルールにより動作しなくなりました。このスクリプトは私が現在使用しているものであり、うまく機能しているようです(ただし、明らかに私のセットアップに固有のものです)。また、メインアップリンク(eth1)専用の新しいテーブル21を作成しました。

# Add relevant iptables entries.
iptables -t mangle -A OUTPUT -m owner --uid-owner 1002 -j MARK --set-mark 11
iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE

# Flush ALL THE THINGS.
ip route flush table main
ip route flush table 11
ip route flush table 21
ip rule flush

# Restore the basic rules and add our own.
ip rule add lookup default priority 32767
ip rule add lookup main priority 32766
ip rule add fwmark 11 priority 1000 table 11
# This next rule basically sends all other traffic down eth1.
ip rule add priority 2000 table 21

# Restore the main table.  I flushed it because OpenVPN does weird things to it.
ip route add 127.0.0.0/8 via 127.0.0.1 dev lo
ip route add 192.168.1.0/24 dev eth1 src 192.168.1.73
ip route add default via 192.168.1.254

# Set up table 21.  This sends all traffic to eth1.
ip route add 192.168.1.0/24 dev eth1 table 21
ip route add default via 192.168.1.254 dev eth1 table 21

# Set up table 11.  I honestly don't know why 'default' won't work, or
# why the second line here is needed.  But it works this way.
ip route add 10.32.0.49/32 dev tun0 table 11
ip route add 10.32.0.1 via 10.32.0.50 dev tun0 table 11
ip route add 0.0.0.0/1 via 10.32.0.50 dev tun0 table 11

ip route flush cache

## MeanderingCodeの編集(まだコメントできないため)

この答えをありがとう!ここでルート情報を維持する必要があるため、これは面倒になる可能性があるようです(おそらく、複製したり、ルートを設定したい他のものを壊したりします)。

サーバーがルートを「プッシュ」するように構成されているため、OpenVPNのルーティングテーブルで「奇妙なこと」が発生している可能性があります。または、OpenVPN構成またはそれを設定するスクリプト/アプリケーションがルートを設定しています。

前者の場合、あなたはあなたのOpenVPNの設定を編集することができますし、「ルート・nopull」を含む行に入れて
(現在の多くのLinuxデスクトップディストリビューション上で、たとえば、ネットワーク・マネージャ- openvpnの)OpenVPNのか、いずれかのラッパーの後者、チェック構成では
Inをどちらの場合でも、このスクリプトを実行するタイミングやシステムのその他の動作に応じて、設定されるルーティング構成を削除する方が、テーブルをフラッシュするよりもクリーンで安全です。

乾杯!


2

あなたが欲しいと思う:

/sbin/ip route add default via 10.32.0.49 dev tun0 table 11
/sbin/ip rule add priority 10000 fwmark 11 table 11

http://lartc.org/howto/lartc.netfilter.html

しかし、私は上記をテストしていません。


最初のコマンドは、「エラー:「to」が重複しているか、「10.32.0.49」がゴミです」を返します。
イーサン

デフォルトとIP間のビアを忘れてしまいました。
mfarver

私はそれを試してみました。defaultキーワードを省略した場合と同じ効果があるようです。
イーサン

オプションを排除するには、tun0でパケットキャプチャを実行し、そのインターフェイスでパケットが終了するかどうかを確認します。tcpdump -i tun0 ..あるいは、ユーザーIDをベースにする必要がありますか?宛先IPアドレスに基づいてそれを行うことができますか?ルートは10.32.0.49を介して<リモートホスト>を追加します
mfarver

宛先IPアドレスがオフの場合、ベースにすることができません-それらの多くがあります。理論的にはpidを基にすることもできますが、デーモンが起動するまでpidがわからないため、それはさらに困難です。
イーサン

0

これは、iptablesコマンドなしで実行できます。シンプルなipコマンドを実行します。

uid 1002の場合:

ip rule add uidrange 1002-1002 table 502

あなたが言いたいインターフェイスを介してテーブル502のデフォルトルートを追加します

eth0 ip rule add default via a.b.c.d dev eth0

私はそのコマンドをテストしましたが、機能しませんでした:Error: argument "uidrange" is wrong: Failed to parse rule type
kasperd

@kasperdあなたは彼がそれを間違っていたに違いない、それは私にとってはうまくいくからだ。
ホージーガイ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.