Install Iptables rules to set TCPMSS for 'lo' interface (#3452)
* Install Iptables rules to set TCPMSS for lo interface * Moved implementation to hostcfgd to maintain at one place
This commit is contained in:
parent
9f03af0a2e
commit
4ef5ce74e4
@ -7,6 +7,7 @@ import subprocess
|
|||||||
import syslog
|
import syslog
|
||||||
import copy
|
import copy
|
||||||
import jinja2
|
import jinja2
|
||||||
|
import ipaddr as ipaddress
|
||||||
from swsssdk import ConfigDBConnector
|
from swsssdk import ConfigDBConnector
|
||||||
|
|
||||||
# FILE
|
# FILE
|
||||||
@ -39,6 +40,82 @@ def obfuscate(data):
|
|||||||
else:
|
else:
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
class Iptables(object):
|
||||||
|
def __init__(self):
|
||||||
|
'''
|
||||||
|
Default MSS to 1460 - (MTU 1500 - 40 (TCP/IP Overhead))
|
||||||
|
For IPv6, it would be 1440 - (MTU 1500 - 60 octects)
|
||||||
|
'''
|
||||||
|
self.tcpmss = 1460
|
||||||
|
self.tcp6mss = 1440
|
||||||
|
|
||||||
|
def is_ip_prefix_in_key(self, key):
|
||||||
|
'''
|
||||||
|
Function to check if IP address is present in the key. If it
|
||||||
|
is present, then the key would be a tuple or else, it shall be
|
||||||
|
be string
|
||||||
|
'''
|
||||||
|
return (isinstance(key, tuple))
|
||||||
|
|
||||||
|
def load(self, lpbk_table):
|
||||||
|
for row in lpbk_table:
|
||||||
|
self.iptables_handler(row, lpbk_table[row])
|
||||||
|
|
||||||
|
def command(self, chain, ip, ver, op):
|
||||||
|
cmd = 'iptables' if ver == '4' else 'ip6tables'
|
||||||
|
cmd += ' -t mangle --{} {} -p tcp --tcp-flags SYN SYN'.format(op, chain)
|
||||||
|
cmd += ' -d' if chain == 'PREROUTING' else ' -s'
|
||||||
|
mss = self.tcpmss if ver == '4' else self.tcp6mss
|
||||||
|
cmd += ' {} -j TCPMSS --set-mss {}'.format(ip, mss)
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
|
||||||
|
def iptables_handler(self, key, data, add=True):
|
||||||
|
if not self.is_ip_prefix_in_key(key):
|
||||||
|
return
|
||||||
|
|
||||||
|
iface, ip = key
|
||||||
|
ip_str = ip.split("/")[0]
|
||||||
|
ip_addr = ipaddress.IPAddress(ip_str)
|
||||||
|
if isinstance(ip_addr, ipaddress.IPv6Address):
|
||||||
|
ver = '6'
|
||||||
|
else:
|
||||||
|
ver = '4'
|
||||||
|
|
||||||
|
self.mangle_handler(ip_str, ver, add)
|
||||||
|
|
||||||
|
def mangle_handler(self, ip, ver, add):
|
||||||
|
if not add:
|
||||||
|
op = 'delete'
|
||||||
|
else:
|
||||||
|
op = 'check'
|
||||||
|
|
||||||
|
iptables_cmds = []
|
||||||
|
chains = ['PREROUTING', 'POSTROUTING']
|
||||||
|
for chain in chains:
|
||||||
|
cmd = self.command(chain, ip, ver, op)
|
||||||
|
if not add:
|
||||||
|
iptables_cmds.append(cmd)
|
||||||
|
else:
|
||||||
|
'''
|
||||||
|
For add case, first check if rule exists. Iptables just appends to the chain
|
||||||
|
as a new rule even if it is the same as an existing one. Check this and
|
||||||
|
do nothing if rule exists
|
||||||
|
'''
|
||||||
|
ret = subprocess.call(cmd, shell=True)
|
||||||
|
if ret == 0:
|
||||||
|
syslog.syslog(syslog.LOG_INFO, "{} rule exists in {}".format(ip, chain))
|
||||||
|
else:
|
||||||
|
# Modify command from Check to Append
|
||||||
|
iptables_cmds.append(cmd.replace("check", "append"))
|
||||||
|
|
||||||
|
for cmd in iptables_cmds:
|
||||||
|
syslog.syslog(syslog.LOG_INFO, "Running cmd - {}".format(cmd))
|
||||||
|
try:
|
||||||
|
subprocess.check_call(cmd, shell=True)
|
||||||
|
except subprocess.CalledProcessError as err:
|
||||||
|
syslog.syslog(syslog.LOG_ERR, "{} - failed: return code - {}, output:\n{}"
|
||||||
|
.format(err.cmd, err.returncode, err.output))
|
||||||
|
|
||||||
class AaaCfg(object):
|
class AaaCfg(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -148,6 +225,9 @@ class HostConfigDaemon:
|
|||||||
tacacs_server = self.config_db.get_table('TACPLUS_SERVER')
|
tacacs_server = self.config_db.get_table('TACPLUS_SERVER')
|
||||||
self.aaacfg = AaaCfg()
|
self.aaacfg = AaaCfg()
|
||||||
self.aaacfg.load(aaa, tacacs_global, tacacs_server)
|
self.aaacfg.load(aaa, tacacs_global, tacacs_server)
|
||||||
|
lpbk_table = self.config_db.get_table('LOOPBACK_INTERFACE')
|
||||||
|
self.iptables = Iptables()
|
||||||
|
self.iptables.load(lpbk_table)
|
||||||
|
|
||||||
def aaa_handler(self, key, data):
|
def aaa_handler(self, key, data):
|
||||||
self.aaacfg.aaa_update(key, data)
|
self.aaacfg.aaa_update(key, data)
|
||||||
@ -166,10 +246,22 @@ class HostConfigDaemon:
|
|||||||
log_data['passkey'] = obfuscate(log_data['passkey'])
|
log_data['passkey'] = obfuscate(log_data['passkey'])
|
||||||
syslog.syslog(syslog.LOG_INFO, 'value of {} changed to {}'.format(key, log_data))
|
syslog.syslog(syslog.LOG_INFO, 'value of {} changed to {}'.format(key, log_data))
|
||||||
|
|
||||||
|
def lpbk_handler(self, key, data):
|
||||||
|
key = ConfigDBConnector.deserialize_key(key)
|
||||||
|
#Check if delete operation by fetch existing keys
|
||||||
|
keys = self.config_db.get_keys('LOOPBACK_INTERFACE')
|
||||||
|
if key in keys:
|
||||||
|
add = True
|
||||||
|
else:
|
||||||
|
add = False
|
||||||
|
|
||||||
|
self.iptables.iptables_handler(key, data, add)
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
self.config_db.subscribe('AAA', lambda table, key, data: self.aaa_handler(key, data))
|
self.config_db.subscribe('AAA', lambda table, key, data: self.aaa_handler(key, data))
|
||||||
self.config_db.subscribe('TACPLUS_SERVER', lambda table, key, data: self.tacacs_server_handler(key, data))
|
self.config_db.subscribe('TACPLUS_SERVER', lambda table, key, data: self.tacacs_server_handler(key, data))
|
||||||
self.config_db.subscribe('TACPLUS', lambda table, key, data: self.tacacs_global_handler(key, data))
|
self.config_db.subscribe('TACPLUS', lambda table, key, data: self.tacacs_global_handler(key, data))
|
||||||
|
self.config_db.subscribe('LOOPBACK_INTERFACE', lambda table, key, data: self.lpbk_handler(key, data))
|
||||||
self.config_db.listen()
|
self.config_db.listen()
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user