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