@@ -8,6 +8,7 @@ import subprocess
8
8
import syslog
9
9
import copy
10
10
import jinja2
11
+ import ipaddr as ipaddress
11
12
from swsssdk import ConfigDBConnector
12
13
13
14
# FILE
@@ -49,6 +50,82 @@ def obfuscate(data):
49
50
else :
50
51
return data
51
52
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 ))
52
129
53
130
class AaaCfg (object ):
54
131
def __init__ (self ):
@@ -159,6 +236,9 @@ class HostConfigDaemon:
159
236
self .aaacfg = AaaCfg ()
160
237
self .aaacfg .load (aaa , tacacs_global , tacacs_server )
161
238
self .hostname_cache = ""
239
+ lpbk_table = self .config_db .get_table ('LOOPBACK_INTERFACE' )
240
+ self .iptables = Iptables ()
241
+ self .iptables .load (lpbk_table )
162
242
163
243
def aaa_handler (self , key , data ):
164
244
self .aaacfg .aaa_update (key , data )
@@ -215,11 +295,23 @@ class HostConfigDaemon:
215
295
216
296
self .hostname_cache = hostname
217
297
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
+
218
309
def start (self ):
219
310
self .config_db .subscribe ('AAA' , lambda table , key , data : self .aaa_handler (key , data ))
220
311
self .config_db .subscribe ('TACPLUS_SERVER' , lambda table , key , data : self .tacacs_server_handler (key , data ))
221
312
self .config_db .subscribe ('TACPLUS' , lambda table , key , data : self .tacacs_global_handler (key , data ))
222
313
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 ))
223
315
self .config_db .listen ()
224
316
225
317
0 commit comments