Skip to content

Commit 8ca1eb2

Browse files
authored
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
1 parent 3c0b56a commit 8ca1eb2

File tree

1 file changed

+92
-0
lines changed

1 file changed

+92
-0
lines changed

files/image_config/hostcfgd/hostcfgd

+92
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import subprocess
88
import syslog
99
import copy
1010
import jinja2
11+
import ipaddr as ipaddress
1112
from swsssdk import ConfigDBConnector
1213

1314
# FILE
@@ -49,6 +50,82 @@ def obfuscate(data):
4950
else:
5051
return data
5152

53+
class Iptables(object):
54+
def __init__(self):
55+
'''
56+
Default MSS to 1460 - (MTU 1500 - 40 (TCP/IP Overhead))
57+
For IPv6, it would be 1440 - (MTU 1500 - 60 octects)
58+
'''
59+
self.tcpmss = 1460
60+
self.tcp6mss = 1440
61+
62+
def is_ip_prefix_in_key(self, key):
63+
'''
64+
Function to check if IP address is present in the key. If it
65+
is present, then the key would be a tuple or else, it shall be
66+
be string
67+
'''
68+
return (isinstance(key, tuple))
69+
70+
def load(self, lpbk_table):
71+
for row in lpbk_table:
72+
self.iptables_handler(row, lpbk_table[row])
73+
74+
def command(self, chain, ip, ver, op):
75+
cmd = 'iptables' if ver == '4' else 'ip6tables'
76+
cmd += ' -t mangle --{} {} -p tcp --tcp-flags SYN SYN'.format(op, chain)
77+
cmd += ' -d' if chain == 'PREROUTING' else ' -s'
78+
mss = self.tcpmss if ver == '4' else self.tcp6mss
79+
cmd += ' {} -j TCPMSS --set-mss {}'.format(ip, mss)
80+
81+
return cmd
82+
83+
def iptables_handler(self, key, data, add=True):
84+
if not self.is_ip_prefix_in_key(key):
85+
return
86+
87+
iface, ip = key
88+
ip_str = ip.split("/")[0]
89+
ip_addr = ipaddress.IPAddress(ip_str)
90+
if isinstance(ip_addr, ipaddress.IPv6Address):
91+
ver = '6'
92+
else:
93+
ver = '4'
94+
95+
self.mangle_handler(ip_str, ver, add)
96+
97+
def mangle_handler(self, ip, ver, add):
98+
if not add:
99+
op = 'delete'
100+
else:
101+
op = 'check'
102+
103+
iptables_cmds = []
104+
chains = ['PREROUTING', 'POSTROUTING']
105+
for chain in chains:
106+
cmd = self.command(chain, ip, ver, op)
107+
if not add:
108+
iptables_cmds.append(cmd)
109+
else:
110+
'''
111+
For add case, first check if rule exists. Iptables just appends to the chain
112+
as a new rule even if it is the same as an existing one. Check this and
113+
do nothing if rule exists
114+
'''
115+
ret = subprocess.call(cmd, shell=True)
116+
if ret == 0:
117+
syslog.syslog(syslog.LOG_INFO, "{} rule exists in {}".format(ip, chain))
118+
else:
119+
# Modify command from Check to Append
120+
iptables_cmds.append(cmd.replace("check", "append"))
121+
122+
for cmd in iptables_cmds:
123+
syslog.syslog(syslog.LOG_INFO, "Running cmd - {}".format(cmd))
124+
try:
125+
subprocess.check_call(cmd, shell=True)
126+
except subprocess.CalledProcessError as err:
127+
syslog.syslog(syslog.LOG_ERR, "{} - failed: return code - {}, output:\n{}"
128+
.format(err.cmd, err.returncode, err.output))
52129

53130
class AaaCfg(object):
54131
def __init__(self):
@@ -159,6 +236,9 @@ class HostConfigDaemon:
159236
self.aaacfg = AaaCfg()
160237
self.aaacfg.load(aaa, tacacs_global, tacacs_server)
161238
self.hostname_cache=""
239+
lpbk_table = self.config_db.get_table('LOOPBACK_INTERFACE')
240+
self.iptables = Iptables()
241+
self.iptables.load(lpbk_table)
162242

163243
def aaa_handler(self, key, data):
164244
self.aaacfg.aaa_update(key, data)
@@ -215,11 +295,23 @@ class HostConfigDaemon:
215295

216296
self.hostname_cache = hostname
217297

298+
def lpbk_handler(self, key, data):
299+
key = ConfigDBConnector.deserialize_key(key)
300+
#Check if delete operation by fetch existing keys
301+
keys = self.config_db.get_keys('LOOPBACK_INTERFACE')
302+
if key in keys:
303+
add = True
304+
else:
305+
add = False
306+
307+
self.iptables.iptables_handler(key, data, add)
308+
218309
def start(self):
219310
self.config_db.subscribe('AAA', lambda table, key, data: self.aaa_handler(key, data))
220311
self.config_db.subscribe('TACPLUS_SERVER', lambda table, key, data: self.tacacs_server_handler(key, data))
221312
self.config_db.subscribe('TACPLUS', lambda table, key, data: self.tacacs_global_handler(key, data))
222313
self.config_db.subscribe('DEVICE_METADATA', lambda table, key, data: self.hostname_handler(key, data))
314+
self.config_db.subscribe('LOOPBACK_INTERFACE', lambda table, key, data: self.lpbk_handler(key, data))
223315
self.config_db.listen()
224316

225317

0 commit comments

Comments
 (0)