#! / usr / bin / env python
# - * - coding: utf-8 - * -
')
# settings are here
ifaces = [
{
"dev" : "eth1" ,
"ip" : "192.168.0.1" ,
"role" : "local"
} ,
{
"dev" : "eth2"
} ,
{
"dev" : "eth3" ,
"ip" : "1.2.3.4" ,
"gw" : "1.2.3.1" ,
"table" : "NewComPort" ,
"mark" : "0x2" ,
"role" : "external" ,
"weight" : 7
} ,
{
"dev" : "ppp0" ,
"gw" : "5.6.7.1" ,
"table" : "velnet" ,
"mark" : "0x1" ,
"role" : "external" ,
"weight" : 3
} ,
{
"dev" : "tun0" ,
"ip" : "192.168.1.1" ,
"table" : "VPN" ,
"mark" : "0x4" ,
"role" : "local"
}
]
Ports = [
{
"proto" : "tcp" ,
"tPort" : 22 ,
"sHost" : None ,
"nPort" : None ,
"dHost" : None
}
,
{ # let's solve the whole protocol right away
"proto" : "icmp" ,
"tPort" : None ,
"sHost" : None ,
"nPort" : None ,
"dHost" : None
}
,
{ # forwarding RDP from internet to LAN on 192.168.0.3
"proto" : "tcp" ,
"tPort" : 3389 ,
"sHost" : None ,
"nPort" : 3389 ,
"dHost" : "192.168.0.3"
}
,
{ # forwarding RDP from Internet with port changed to 3390 to 192.168.0.2
"proto" : "tcp" ,
"tPort" : 3390 ,
"sHost" : None ,
"nPort" : 3389 ,
"dHost" : "192.168.0.2"
}
,
{ # web control from only one remote host
"proto" : "tcp" ,
"tPort" : 80 ,
"sHost" : "9.8.7.6" ,
"nPort" : None ,
"dHost" : None
}
,
{ # openVPN for all
"proto" : "tcp" ,
"tPort" : 1194 ,
"sHost" : None ,
"nPort" : None ,
"dHost" : None
}
]
rules = [
{ # provider statistics through his gateway
"to" : "213.79.2.30" , # stats
"lookup" : "velnet"
} ,
{ # VMs on VM table
"from" : "192.168.0.150" ,
"lookup" : "VM"
} ,
{ # VMs on VM table
"from" : "192.168.0.151" ,
"lookup" : "VM"
}
]
routes = [
{ # Network behind VPN client
"to" : "192.168.8.0" ,
"dev" : "tun0"
} ,
{ # VM virtualok table through one provider
"to" : "default" ,
"via" : "5.6.7.8" ,
"dev" : "ppp0" ,
"table" : "VM"
}
]
ext_sure_ip = "8.8.8.8"
customcommands = "" "
"" "
cmdfile = "/root/msr_ip.run"
# == no more configuration settings below this line =======================
import os
import syslog
import subprocess
syslog syslog ( "Started" )
fields = ( "dev" , "ip" , "gw" , "table" , "mark" , "works" , "state" , "role" , "type" , "weight" )
fout = open ( cmdfile, 'w' )
priority = 1
# == add system's rules
rules = rules + [
{ "priority" : 100 , "from" : "all" , "lookup" : "local" } ,
{ "priority" : 32766 , "from" : "all" , "lookup" : "main" } ,
{ "priority" : 32767 , "from" : "all" , "lookup" : "default" }
]
def isup ( dev ) :
x = subprocess . call ( [ "ifconfig" , dev ] , stdin = None , stdout = open ( '/ dev / null' , 'w' ) , stderr = open ( '/ dev / null' , 'w' ) , shell = False )
if ( x == 0 ) :
r = "up"
else :
r = "down"
return r
def works ( dev ) :
# global ext_sure_ip
x = subprocess . 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
else :
r = False
return r
def addmissingfields ( iface ) :
for fld in fields:
if not ( fld in iface ) :
iface [ fld ] = None
def openportcmd ( port ) :
r = "n $ IPTABLES -t filter -A INPUT"
if port [ "sHost" ] :
r = r + "-s {0}" . format ( port [ "sHost" ] )
if port [ "proto" ] :
r = r + "-p {0}" . format ( port [ "proto" ] )
if port [ "tPort" ] :
r = r + "--dport {0}" . format ( port [ "tPort" ] )
r = r + "-j ACCEPT"
return r
def forwardportcmd ( port ) :
if port [ "dHost" ] :
# allow $ IPTABLES -A FORWARD -p tcp --dport 3389 -j ACCEPT
r = "n $ IPTABLES -A FORWARD"
if port [ "proto" ] :
r = r + "-p {0}" . format ( port [ "proto" ] )
if port [ "nPort" ] :
r = r + "--dport {0}" . format ( port [ "nPort" ] )
r = r + "-j ACCEPT"
# forward
r = r + "n $ IPTABLES -t nat -A PREROUTING"
if port [ "sHost" ] :
r = r + "-s {0}" . format ( port [ "sHost" ] )
if port [ "proto" ] :
r = r + "-p {0}" . format ( port [ "proto" ] )
if port [ "tPort" ] :
r = r + "--dport {0}" . format ( port [ "tPort" ] )
r = r + "-j DNAT --to-destination {0}" . format ( port [ "dHost" ] )
if port [ "nPort" ] :
r = r + ": {0}" . format ( port [ "nPort" ] )
return r
else :
return ""
def rulecmd ( rule ) :
global priority
priority = priority + 1
r = "nip rule"
if ( "cmd" in rule ) and ( rule [ "cmd" ] ) :
r = r + "{0}" . rule [ "cmd" ]
else :
r = r + "add"
if ( "priority" in rule ) and ( rule [ "priority" ] ) :
r = r + "priority {0}" . format ( rule [ "priority" ] )
else :
r = r + "priority {0}" . format ( priority )
if ( "fwmark" in rule ) and ( rule [ "fwmark" ] ) :
r = r + "fwmark {0} / {0}" . format ( rule [ "fwmark" ] )
if ( "from" in rule ) and ( rule [ "from" ] ) :
r = r + "from {0}" . format ( rule [ "from" ] )
if ( "to" in rule ) and ( rule [ "to" ] ) :
r = r + "to {0}" . format ( rule [ "to" ] )
if ( "lookup" in rule ) and ( rule [ "lookup" ] ) :
r = r + "lookup {0}" . format ( rule [ "lookup" ] )
return r
def routecmd ( route ) :
r = "nip route add"
if ( "to" in route ) and ( route [ "to" ] ) :
r = r + "{0}" . format ( route [ "to" ] )
# if ("netmask" in route) and (route ["netmask"]):
# r = r + "/ {0}". format (route ["netmask"])
if ( "via" in route ) and ( route [ "via" ] ) :
r = r + "via {0}" . format ( route [ "via" ] )
if ( "dev" in route ) and ( route [ "dev" ] ) :
r = r + "dev {0}" . format ( route [ "dev" ] )
if ( "table" in route ) and ( route [ "table" ] ) :
r = r + "table {0}" . format ( route [ "table" ] )
return r
portion = "" "#! / bin / sh
# == set variables ===========================================
IPTABLES = / sbin / iptables
"" "
fout. write ( portion )
fout. write ( "n # == interfaces:" )
for iface in ifaces:
addmissingfields ( iface )
iface [ "state" ] = isup ( iface [ "dev" ] )
if ( iface [ "role" ] == "external" ) :
iface [ "works" ] = works ( iface [ "dev" ] )
descr = "{3} {0} is {1} and works = {2}" . format ( iface [ "dev" ] , iface [ "state" ] , iface [ "works" ] , iface [ "role" ] )
fout. write ( "n #" + descr )
syslog syslog ( descr )
portion = "" "
# == Disallow forwarding during script running ========================================
echo 0> / proc / sys / net / ipv4 / ip_forward
# == Drop all rules at script running ========================================
ip rule flush
# == delete all existing policies ===============================
$ IPTABLES -F
$ IPTABLES -t nat -F
$ IPTABLES -t mangle -F
$ IPTABLES -X
$ IPTABLES -Z
# == Set default policies ====================================
$ IPTABLES -P INPUT DROP
$ IPTABLES -P OUTPUT ACCEPT
$ IPTABLES -P FORWARD DROP
# == DROP bad packets ========================================
$ 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
# == Only SYN packets establish NEW connections ==============
$ IPTABLES -t filter -A INPUT -p tcp! --syn -m state --state NEW -j DROP
$ IPTABLES -t filter -A OUTPUT -p tcp! --syn -m state --state NEW -j DROP
$ IPTABLES -t filter -A FORWARD -p tcp! --syn -m state --state NEW -j DROP
# == secure lo 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
"" "
fout. write ( portion )
fout. write ( "" "
# == Open & forward ports ================================ "" " )
for port in Ports:
fout. write ( openportcmd ( port ) )
fout. write ( forwardportcmd ( port ) )
fout. write ( "" "
# == between all if, allow, drop, and all masses; ext;
for iface in ifaces:
fout. write ( "n # ==== for {0}" . format ( iface [ "dev" ] ) )
for oface in ifaces:
if ( iface ! = oface ) :
if ( iface [ "role" ] == "local" ) and ( oface [ "role" ] == "local" ) :
fout. write ( "n $ IPTABLES -t filter -A FORWARD -i {0} -o {1} -j ACCEPT" . format ( iface [ "dev" ] , oface [ "dev" ] ) )
if ( iface [ "role" ] == "local" ) and ( oface [ "role" ] == "external" ) :
fout. write ( "n $ IPTABLES -t filter -A FORWARD -i {0} -o {1} -m state - state NEW -j ACCEPT" . format ( iface [ "dev" ] , oface [ "dev" ] ) )
if iface [ "role" ] == "local" :
action = "ACCEPT"
else :
action = "DROP"
fout. write ( "n $ IPTABLES -t filter -A INPUT -i {0} -m state --state NEW -j {1}" . format ( iface [ "dev" ] , action ) )
fout. write ( "n $ IPTABLES -t nat -A POSTROUTING -o {0} -j MASQUERADE" . format ( iface [ "dev" ] ) )
fout. write ( "" "
# == Allow established to forward, others will be dropped by policy
$ IPTABLES -t filter -A FORWARD -m state --state ESTABLISHED, RELATED -j ACCEPT
$ IPTABLES -t filter -A INPUT -m state --state ESTABLISHED, RELATED -j ACCEPT
"" " )
fout. write ( "" "
# == For some ifaces set tables, marks & rules ====================================== ============= "" " )
for iface in ifaces:
if iface [ "table" ] and iface [ "gw" ] and iface [ "table" ] :
fout. write ( "nip route add default via {0} dev {1} table {2}" . format ( iface [ "gw" ] , iface [ "dev" ] , iface [ "table" ] ) )
if iface [ "mark" ] :
fout. write ( rulecmd ( {
"fwmark" : iface [ "mark" ] ,
"lookup" : iface [ "table" ]
} ) )
fout. write ( "" "
# == Answers must be sent thrown incomming iface ================================== "" " )
#for iface in ifaces:
# if if ["mark"]:
# 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")
for iface in ifaces:
if iface [ "table" ] and iface [ "gw" ] :
fout. write ( rulecmd ( {
"from" : iface [ "gw" ] ,
"lookup" : iface [ "table" ]
} ) )
fout. write ( "" "
# == Rules from rules' list ================================= "" "
for rule in rules:
fout. write ( rulecmd ( rule ) )
fout. write ( "" "
# == Routes from routes' list ================================== "" " )
for route in routes:
fout. write ( routecmd ( route ) )
fout. write ( "" "
# == External ifaces interleaving (between all UP ext) =================================== "" " )
portion = "nip route replace default scope global"
for iface in ifaces:
if iface [ "dev" ] and iface [ "gw" ] and iface [ "weight" ] and ( iface [ "role" ] == "external" ) and ( iface [ "state" ] == "up" ) :
portion = portion + "nexthop via {0} dev {1} weight {2}" . format ( iface [ "gw" ] , iface [ "dev" ] , iface [ "weight" ] )
fout. write ( portion )
fout. write ( "" "
# == Allow forwarding ============================================= ===========================
echo 1> / proc / sys / net / ipv4 / ip_forward
"" " )
fout. write ( "" "
# == some handmade custom commands =========================================== ===================
{0}
"" " . format ( customcommands ) )
fout. close ( )
syslog syslog ( "Finished" )
syslog syslog ( "Script started" )
x = subprocess . call ( [ "/ bin / sh" , "{0}" . format ( cmdfile ) ] , stdin = None , stdout = open ( '/ dev / null' , 'w' ) , stderr = open ( '/ dev / null ' , ' w ' ) , shell = False )
syslog syslog ( "Script finished with result {0}" . format ( x ) )
root @ Gate: / root # cat ./msr_on_if_changed#! / bin / sh/ usr / bin / python /root/msr_ip.pyexit 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
Source: https://habr.com/ru/post/138705/
All Articles