質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
Perl

Perlは多目的に使用される実用性が高い動的プログラミング言語のひとつです。

iptables

iptablesは、一般的なLinuxに備わっているパケットフィルタリング型のファイアウォール機能。パケットフィルタリングルールおよびネットワークアドレス変換ルールを適用することが可能です。

ルーティング

ルーティングとは、TCP/IPネットワークにおいて、目的のホストまでパケットを送る為のパス選定のプロセスを言います。

Q&A

解決済

1回答

296閲覧

プログラム内でiptablesを実行時にすぐに適用されない

TAKE147

総合スコア20

Perl

Perlは多目的に使用される実用性が高い動的プログラミング言語のひとつです。

iptables

iptablesは、一般的なLinuxに備わっているパケットフィルタリング型のファイアウォール機能。パケットフィルタリングルールおよびネットワークアドレス変換ルールを適用することが可能です。

ルーティング

ルーティングとは、TCP/IPネットワークにおいて、目的のホストまでパケットを送る為のパス選定のプロセスを言います。

0グッド

0クリップ

投稿2022/09/28 07:10

前提と問題点

複数の仮想マシンで仮想ネットワークを作成し、webサーバマシンにて以下のプログラムを実行し、クライアントからwebサーバマシンにhttperfでアクセスする。ルーティングテーブルはメイン=rt1,rt2の二つあり、クライアントからwebサーバまでの経路は一本道だが、webサーバからクライアントまでの経路はrt1,rt2の二つの経路がある。
本来はrt1を参照するが、プログラムを実行している間に送信されるパケットはrt2を参照したい。
しかし、実際にプログラムを動かすと一つ目のコネクション
のパケットはrt1を参照して、二つ目以降のコネクションのパケットはrt2を参照する。

実現したいこと

  • iptables -A PREROUTING -i eth3 -p tcp -j MARK --set-mark $mark をプログラム内で実行した瞬間から適用されてほしい
  • 適用されてほしいというのは一つ目のコネクションのパケットからちゃんとrt2を参照してほしいということです。

該当のソースコード

perl

1#!/usr/bin/perl -sw 2 3$count = 0; 4$debug = 1; 5 6#ループ回数が指定されていないときは10回とする。 7unless ($n) { 8 $n = 10; 9} 10 11# コマンドの出力をパイプでファイルハンドルへ渡す 12$pid = open (PKT, "tcpdump -l -i eth3 -tt -nn '((host 192.168.X.XX) and (tcp) and (src port 80) and (tcp[tcpflags] & (tcp-syn|tcp-fin) != 0))'|"); 13 14# ファイルハンドルからtcpdumpの結果を読み込む 15while (<PKT>) { 16 17 # 時刻(秒)を$1,送信先アドレスを $2,送信先ポートを$3,フラグ[S]or[S.]を$4,シーケンス番号を$5とする 18 if (/^(\d+\.\d+).*> (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}).(\d+).*(Flags \[S\.?\]).*seq (\d+)/) { 19 20 print "---------flag[S]------------\n"; 21 if($debug == 1){ 22 print "\$_ = $_\n"; 23 print "match[S] = $&\n"; 24 } 25 26 #マークは2とする。ip rule によってマーク2はルーティングテーブルrt2を参照する。 27 $mark = 2; 28 print "\$count = $count and \$mark = $mark\n"; 29 30 # iptablesでマークをつける。rt2にルーティングされるようになる(はず) 31 $cmd = "iptables -A PREROUTING -i eth3 -p tcp -t mangle -j MARK --set-mark $mark "; 32 if ($debug == 1) { 33 print "\$cmd = $cmd\n"; 34 } 35 system $cmd; 36 $cmd_3 = "iptables -tmangle -L"; 37 system $cmd_3; 38 # $cmd_restart = "service iptables restart"; 39 # system $cmd_restart; 40 41 #フラグが[F]or[F.]の場合 42 } elsif (/^(\d+\.\d+).*> (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}).(\d+).*(Flags \[F\.?\]).*seq (\d+)/) { 43 44 print "---------------flag[F]---------------\n"; 45 if($debug == 1) { 46 print "\$_ = $_\n"; 47 print "match[F] = $&\n"; 48 } 49 50 $count++; 51 52 #n回読み込んだら終了させる。 53 if ($count == $n) { 54 last; 55 } 56 } 57} 58 59#マーク付けした内容を全て削除する 60$cmd_2 = "iptables -F PREROUTING -t mangle"; 61system $cmd_2; 62 63#クローズする前にプロセスを終了させる。 64kill(15,$pid); 65#使ったらちゃんと閉じる 66close (PKT); 67

試したこと

  • 手動でiptables を設定してマーク付け=ルーティングの変更ができるか

-> できた。予め設定しておく分にはできて、プログラム内のwhileループ内で行おうとするとすぐに適用されなかった。

  • whileより前にiptablesを行うsystemコマンドをかく

-> この方法はできるし、解決にはなりますが、今後の目的のためipttablesは「SYNパケットを読み込んでから、対応したFINパケットを読み込むまでの間」に実行する必要があります。

お願い

説明で不十分な点や不明な点が多いとは思いますが、聞いていただければ捕捉しますのでご協力お願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

okakemetal

2022/09/28 08:07

スクリプトの中で、設定を変えた後に数秒スリープさせてみては いかがでしょうか?
TAKE147

2022/09/28 08:36

申し訳ありません。リアルタイムなtcpdump出力が欲しいのでスリープさせることはできないです。
TAKE147

2022/09/29 01:38

また、system $cmd; を行った後にsleep 3;で3秒待たせてみましたが、1つめのパケットはrt2になりませんでした。
guest

回答1

0

自己解決

ルーティング内容に不備が見つかりました。そのためうまくいかなかったみたいです。アドバイスくださった方、ありがとうございました。

投稿2022/09/30 05:23

TAKE147

総合スコア20

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問