MultiHomed Linuxルーターを構成するスクリプト

ただし、本格的なシステム管理者ではないため、ゲートウェイを構成する必要がしばしば発生します。 これまでのところ、外部インターフェースは1つしかありませんでした。これは、インターネットとlartc.comでコンパイルされた比較的普遍的なbashスクリプトを変更しただけです。 2つのインターネットプロバイダーにオプションがあったとき-変更を容易にするためにグループ化された設定でスクリプトを書くことができました。

スクリプトは次のことができます。



説明



メインのpythonスクリプトは、それ自体の設定に従って、実行されるbashスクリプトを形成するように配置されています。 このようなトリックは無視できないほど重く、声を出すのに十分ではないという理由で判明しました。 リンクの設定スクリプトをダウンロードします。

そして、ここで彼のデバイスが説明されています。



設定



Python msr_ip.pyスクリプトは、必要な入力行で始まります。

#!/ usr / bin / env python

#-*-コーディング:utf-8-*-



#設定はこちら




次に、設定のストリーム、最初にインターフェースの説明が続きます。

ifaces = [

{

"dev""eth1"

「ip」「192.168.0.1」

「ロール」「ローカル」

}

{

"dev""eth2"

}

{

"dev""eth3"

「ip」「1.2.3.4」

"gw""1.2.3.1"

"table""NewComPort"

「マーク」「0x2」

「ロール」「外部」

「重量」7

}

{

"dev""ppp0"

"gw""5.6.7.1"

"table""velnet"

「マーク」「0x1」

「ロール」「外部」

「重量」3

}

{

"dev""tun0"

「ip」「192.168.1.1」

「テーブル」「VPN」

「マーク」「0x4」

「ロール」「ローカル」

}

]


インターフェイスでは、実際には辞書要素である次のプロパティを使用できます。

dev-インターフェイス名、唯一の必須要素。

gw-ゲートウェイ。

table-ルーティングテーブルの番号または名前。名前が指定されている場合は、ファイル/ etc / iproute2 / rt_tablesに既に存在する必要があります。 外部インターフェイスには必須。

mark-パッケージのラベル。使用する独自のルールを追加する場合に使用します。

ロール -ロール。外部、ローカル、またはなし。 外部の場合-インターフェイスはそれぞれ外部と見なされ、NATを実行し、外部からの新しい接続を受け入れません。 ローカルの場合-インターフェイスはローカル:NATであり、外部への新しい接続を作成できます。

weight-ルートベースのアウトバウンド負荷分散の重み。

外部インターフェイスが上げられない場合、デフォルトルートにはリストされません。

次に、開いたり転送したりする必要があるポートについて説明します。

ポート= [

{

"proto""tcp"

"tPort"22

"sHost"なし

「nPort」なし

「dHost」なし

}



{ #プロトコル全体をすぐに有効化

"proto""icmp"

"tPort"なし

"sHost"なし

「nPort」なし

「dHost」なし

}



{ #RDPをインターネットから192.168.0.3のLANに転送する

"proto""tcp"

"tPort"3389

"sHost"なし

「nPort」3389

「dHost」「192.168.0.3」

}



{ #ポートを3390に変更したインターネットからRDPを192.168.0.2のLANに転送

"proto""tcp"

"tPort"3390

"sHost"なし

「nPort」3389

「dHost」「192.168.0.2」

}



{ #1つのリモートホストのみからのWebコントロール

"proto""tcp"

「tPort」80

"sHost""9.8.7.6"

「nPort」なし

「dHost」なし

}



{ #皆のためのopenVPN

"proto""tcp"

"tPort"1194

"sHost"なし

「nPort」なし

「dHost」なし

}

]


例からすべてが明確になりますが、順序については説明します。

proto-プロトコル。

tPort-開く外部ポート。

sHost-必要に応じて、送信元アドレスへの制限。

nPort-転送中の新しいポート。

dHost-ポートが転送されるホスト。



これで、ノードを外部インターフェイスにバインドするためにルールが使用されます。

ルール= [

{ #ゲートウェイを介したプロバイダー統計

"to""213.79.2.30"#統計

「lookup」「velnet」

}

{ #VMテーブルの仮想マシン

「from」「192.168.0.150」

「lookup」「VM」

}

{ #VMテーブルの仮想マシン

「from」「192.168.0.151」

「lookup」「VM」

}

]


この例のルールはいくつかのプロパティを使用しますが、さらに適用できます。ipruleコマンドがサポートするすべてをカバーしようとしました。

cmd-コマンド。デフォルトではadd =ルールを追加します。

priority-指定されていない場合、 優先度は言及された順に1から自動的に番号付けされます。

fwmark-パケットラベル。

from-ソース;

to-宛先;

ルックアップ -テーブル。



今のルート:

ルート= [

{ #VPNクライアントの背後のネットワーク

「to」「192.168.8.0」

"dev""tun0"

}

{ #1つのプロバイダーを介したVMテーブル

"to""default"

"via""5.6.7.8"

"dev""ppp0"

「テーブル」「VM」

}

]



to-宛先;

経由 -どのゲートウェイを介して。

dev-どのインターフェースを介して;

テーブル -どのテーブル。



最後に、設定の最後の部分

ext_sure_ip = "8.8.8.8"

customcommands = "" "

「」

cmdfile = "/root/msr_ip.run"





ext_sure_ip-健全性を確認するためにpingにアドレスする外部インターフェイスの場合、現時点では何にも影響しません。

customcommands-すべての設定後に実行されるコマンド。

cmdfile-結果のスクリプトが書き込まれるファイル。



スクリプト本体



これで、スクリプト自体のみが存在し、これ以上の設定はなくなります。これについては、フラグメントのパーフィーラインがうれしく、レポートします。

#==この行の下にこれ以上構成設定はありません========================



輸入 OS

syslogの インポート

サブプロセスの インポート



syslog syslog "開始済み"



フィールド= "dev""ip""gw""table""mark""works""state""role""type""weight"

fout = open cmdfile、 'w'

優先度= 1



#==システムのルールを追加

ルール=ルール+ [

{ "priority"100"from""all""lookup""local" }

{ "priority"32766"from""all""lookup""main" }

{ "priority"32767"from""all""lookup""default" }

]





def isup dev

x = サブプロセスcall [ "ifconfig" 、dev ] 、stdin = None 、stdout = open '/ dev / null''w' 、stderr = open '/ dev / null''w' 、shell = False

if x == 0

r = 「アップ」

その他

r = 「ダウン」

リターン r



def works dev

#グローバルext_sure_ip

x = サブプロセスcall [ "ping""-I" + dev、 "-c 3""-w 5" 、ext_sure_ip ] 、stdin = None 、stdout = open '/ dev / null''w' 、stderr = open '/ dev / null''w' 、shell = False

if x == 0

r = True

その他

r = False

リターン r



def addmissingfields iface

フィールドのfldの場合:

そうで ない 場合 ifaceのfld

iface [ fld ] = なし



def openportcmd port

r = "n $ IPTABLES -t filter -A INPUT"

ポート[ "sHost" ]の場合

r = r + "-s {0}"形式 ポート[ "sHost" ]

ポート[ "proto" ]の場合

r = r + "-p {0}"フォーマット port [ "proto" ]

ポート[ "tPort" ]の場合

r = r + "--dport {0}"形式 ポート[ "tPort" ]

r = r + "-j ACCEPT"

リターン r



def forwardportcmd port

ポート[ "dHost" ]の場合

#allow $ IPTABLES -A FORWARD -p tcp --dport 3389 -j ACCEPT

r = "n $ IPTABLES -A FORWARD"

ポート[ "proto" ]の場合

r = r + "-p {0}"フォーマット port [ "proto" ]

ポート[ "nPort" ]の場合

r = r + "--dport {0}"形式 ポート[ "nPort" ]

r = r + "-j ACCEPT"



#進む

r = r + "n $ IPTABLES -t nat -A PREROUTING"

ポート[ "sHost" ]の場合

r = r + "-s {0}"形式 ポート[ "sHost" ]

ポート[ "proto" ]の場合

r = r + "-p {0}"フォーマット port [ "proto" ]

ポート[ "tPort" ]の場合

r = r + "--dport {0}"形式 ポート[ "tPort" ]

r = r + "-j DNAT --to-destination {0}"フォーマット port [ "dHost" ]

ポート[ "nPort" ]の場合

r = r + ":{0}"形式 ポート[ "nPort" ]

リターン r

その他

「」を 返す



def rulecmd ルール

グローバル優先

優先度=優先度+ 1

r = 「ニップ規則」

if 規則の"cmd" および 規則[ "cmd" ]

r = r + "{0}"ルール [ "cmd" ]

その他

r = r + 「追加」



if ルールの"優先度" および ルール[ "優先度" ]

r = r + "priority {0}"形式 ルール[ "優先度" ]

その他

r = r + "priority {0}"フォーマット 優先度



if ルールの"fwmark" および ルール[ "fwmark" ]

r = r + "fwmark {0} / {0}"形式 ルール[ "fwmark" ]



if "from" in rule および rule [ "from" ]

r = r + "{0}から"形式 ルール[ "from" ]



if "to" in rule および rule [ "to" ]

r = r + "to {0}"形式 ルール[ "to" ]



if ルールの"lookup" および ルール[ "lookup" ]

r = r + "lookup {0}"形式 ルール[ "lookup" ]



リターン r



def routecmd route

r = "nip route add"

if "to" in route および route [ "to" ]

r = r + "{0}"形式 route [ "to" ]

#if(ルートの「ネットマスク」)および(ルート[「ネットマスク」]):

#r = r + "/ {0}"。format(route ["netmask"])

if "via" route および route [ "via" ]

r = r + "via {0}"形式 route [ "via" ]

if "dev" in route および route [ "dev" ]

r = r + "dev {0}"形式 route [ "dev" ]

if "table" in route および route [ "table" ]

r = r + "テーブル{0}"フォーマット route [ "table" ]

リターン r



部分= "" "#!/ bin / sh



#==変数の設定===========================================

IPTABLES = / sbin / iptables

「」「

f。 書き込み 部分





f。 書き込み "n#== interfaces:"



ifacesのifaceの場合:

addmissingfields iface



iface [ "state" ] = isup iface [ "dev" ]



if iface [ "role" ] == "external"

iface [ "works" ] = works iface [ "dev" ]

descr = "{3} {0}は{1}で動作します= {2}"形式 iface [ "dev" ] 、iface [ "state" ] 、iface [ "works" ] 、iface [ "role" ]

f。 書き込み "n#" + descr

syslog syslog descr



部分= "" "

#==スクリプトの実行中に転送を許可しない=======================================

エコー0> / proc / sys / net / ipv4 / ip_forward

#==スクリプトの実行時にすべてのルールを削除=======================================

IPルールフラッシュ



#==既存のポリシーをすべて削除================================

$ IPTABLES -F

$ IPTABLES -t nat -F

$ IPTABLES -tマングル-F

$ IPTABLES -X

$ IPTABLES -Z



#==デフォルトポリシーの設定===================================

$ IPTABLES -P入力ドロップ

$ IPTABLES -P出力受け入れ

$ IPTABLES -Pフォワードドロップ



#==不良パケットの削除========================================

$ IPTABLES -t filter -A INPUT -m state --state INVALID -j DROP

$ IPTABLES -t filter -A OUTPUT -m state --state INVALID -j DROP

$ IPTABLES -t filter -A OUTPUT -m state --state INVALID -j DROP



#== SYNパケットのみが新しい接続を確立します================

$ IPTABLES -t filter -A INPUT -p tcp! --syn -m state --state NEW -j DROP

$ IPTABLES -tフィルター-A出力-p tcp! --syn -m state --state NEW -j DROP

$ IPTABLES -t filter -A FORWARD -p tcp! --syn -m state --state NEW -j DROP



#==安全なiface =========================================

$ IPTABLES -t filter -A FORWARD -i lo -j DROP

$ IPTABLES -t filter -A FORWARD -o lo -j DROP

$ IPTABLES -t filter -A OUTPUT -o lo -s 127.0.0.1/255.0.0.0 -j ACCEPT

$ IPTABLES -t filter -A INPUT -i lo -d 127.0.0.1/255.0.0.0 -j ACCEPT

$ IPTABLES -t filter -A OUTPUT -o lo -j DROP

$ IPTABLES -t filter -A INPUT -i lo -j DROP



「」「



f。 書き込み 部分



f。 書き込み "" "



#==ポートを開いて転送する================================ "" "

ポートインポートの場合:

f。 書き込み openportcmd port

f。 書き込み forwardportcmd port



f。 書き込み "" "



#==すべての場合:すべてのloc-locを許可、新しいloc 2 extを許可、extからnewをドロップ、extにマスカレード "" "

ifacesのifaceの場合:

f。 write "n#==== for {0}"format iface [ "dev" ]

ifacesのofaceの場合:

if iface = oface

if iface [ "role" ] == "local" および oface [ "role" ] == "local"

f。 write "n $ IPTABLES -t filter -A FORWARD -i {0} -o {1} -j ACCEPT" 。format iface [ "dev" ] 、oface [ "dev" ]

if iface [ "role" ] == "local" および oface [ "role" ] == "external"

f。 write "n $ IPTABLES -t filter -A FORWARD -i {0} -o {1} -m state --state NEW -j ACCEPT"。format iface [ "dev" ] 、oface [ "dev" ]



iface [ "role" ] == "local"

action = "ACCEPT"

その他

アクション= 「ドロップ」

f。 write "n $ IPTABLES -t filter -A INPUT -i {0} -m state --state NEW -j {1}"format iface [ "dev" ] 、action



f。 書き込み "n $ IPTABLES -t nat -A POSTROUTING -o {0} -j MASQUERADE"。format iface [ "dev" ]





f。 書き込み "" "



#==確立された転送を許可、他はポリシーによってドロップされます

$ IPTABLES -t filter -A FORWARD -m state --state ESTABLISHED、RELATED -j ACCEPT

$ IPTABLES -t filter -A INPUT -m state --state ESTABLISHED、RELATED -j ACCEPT



「」「」





f。 書き込み "" "

#==一部のifacesセットテーブル、マークとルール====================================== ============== "" "

ifacesのifaceの場合:



iface [ "table" ] および iface [ "gw" ] および iface [ "table" ]

f。 書き込み 「{0} dev {1}テーブル{2}を介したデフォルトのnipルート追加」 フォーマット iface [ "gw" ] 、iface [ "dev" ] 、iface [ "table" ]



iface [ "マーク" ]

f。 書き込み rulecmd {

"fwmark" :iface [ "マーク" ]

"lookup" :iface [ "テーブル" ]

}





f。 書き込み "" "



#== ifaceを介して回答を送信する必要があります================================== "" "

#ifacesのifaceの場合:

#iface ["マーク"]:

#fout.write( "n $ IPTABLES -t mangle -A INPUT -i {0} -j CONNMARK --set-mark {1}"。format(iface ["dev"]、iface ["mark"]))

#fout.write( "n $ IPTABLES -t mangle -A OUTPUT -j CONNMARK --restore-markn")

ifacesのifaceの場合:

iface [ "table" ] および iface [ "gw" ]

f。 書き込み rulecmd {

「from」 :iface [ "gw" ]

"lookup" :iface [ "テーブル" ]

}



f。 書き込み "" "



#==ルールのリストからのルール================================== "" "

ルールのルールの場合:

f。 書き込み rulecmd rule



f。 書き込み "" "



#==ルートのリストからのルート================================== "" "

ルート内のルートの場合:

f。 書き込み routecmd route



f。 書き込み "" "



#==外部ifacesインターリーブ(すべてのUP ext間)=================================== "" "

部分= 「nip route replace default scope global」

ifacesのifaceの場合:

iface [ "dev" ] および iface [ "gw" ] および iface [ "weight" ] および iface [ "role" ] == "external" および iface [ "state" ] == "up"

portion = portion + "nexthop via {0} dev {1} weight {2}"形式 iface [ "gw" ] 、iface [ "dev" ] 、iface [ "weight" ]

f。 書き込み 部分



f。 書き込み "" "



#==転送を許可============================================ =============================

エコー1> / proc / sys / net / ipv4 / ip_forward

「」「」



f。 書き込み "" "



#==いくつかの手作りのカスタムコマンド========================================== =====================

{0}

"" " 。format customcommands





f。 閉じる



syslog syslog "完了"

syslog syslog "スクリプトが開始されました"

x = サブプロセスcall [ "/ bin / sh""{0}"format cmdfile ] 、stdin = None 、stdout = open '/ dev / null''w' 、stderr = open '/ dev / null '' w ' 、shell = False

syslog syslog "スクリプトは結果{0}で終了しました"。format x






打ち上げ



現在使用しているオプションの1つは、インターフェイスを変更するときにスクリプトを呼び出すことです。 このために、呼び出しスクリプトが書かれています:

 
  ルート@ゲート:/ルート#cat ./msr_on_if_changed  
  #!/ bin / sh 
  / usr / bin / python /root/msr_ip.py 
  出口0 
 


スクリプトへのリンクは、ネットワークインターフェイス構成ディレクトリにインストールされます。 主なことは、名前が拡張子なしになることです。そうしないと、初期化システムによってリンクが無視されます。

 ln -s /root/msr_ip.py / etc / network / if-down / msr_ip
 ln -s /root/msr_ip.py / etc / network / if-up / msr_ip
 ln -s /root/msr_ip.py /etc/ppp/ip-up.d/msr_ip
 ln -s /root/msr_ip.py /etc/ppp/ip-down.d/msr_ip


合計



このスクリプトは3か月間実行されており、これまでのところ、その障害による障害はありませんでした。



All Articles