スクリプトは次のことができます。
- NATを使用してインターネット配信を構成する
- オープンポート
- フォワードポート
- 複数のプロバイダーを使用する
- さらに説明されたルールとルートを適用する
- 追加の所定のコマンドを実行する
説明
メインの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か月間実行されており、これまでのところ、その障害による障害はありませんでした。