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か月間実行されており、これまでのところ、その障害による障害はありませんでした。

Source: https://habr.com/ru/post/J138705/


All Articles