def __init__(self, shared_=None, log_fn=print): self.callout = win32file.CreateFile( self.CALLOUT_DRIVER_NAME, win32file.GENERIC_READ | win32file.GENERIC_WRITE, win32file.FILE_SHARE_READ, None, win32file.OPEN_EXISTING, 0, 0) self.log = log_fn if shared_ is None: self.shared = RAVerifier(self.log) else: self.shared = shared_
def __init__(self, config=None, socket_=None, verifier=None): if socket_ is None: self.socket = socket.socket(socket.PF_SYSTEM, socket.SOCK_STREAM, socket.SYSPROTO_CONTROL) else: self.socket = socket_ if verifier is None: syslog.openlog("TrustRouter") def log(string): syslog.syslog(syslog.LOG_ALERT, string) self.verifier = RAVerifier(log, config) else: self.verifier = verifier
def cb(payload): print("python callback called!") common_part = RAVerifier() sock = socket.socket( socket.AF_INET6, socket.SOCK_RAW, IPPROTO_ICMPV6) sock.settimeout(2) if common_part.verify( payload.get_data(), payload.get_indev(), sock): payload.set_verdict(nfqueue.NF_ACCEPT) else: payload.set_verdict(nfqueue.NF_DROP) sys.stdout.flush() return 1
class TestMac(unittest.TestCase): RA_PACKET = b"\x60\x00\x00\x00\x01\xc8\x3a\xff\xfe\x80\x00\x00\x00\x00\x00\x00\x2c\xf2\x7e\xf7\x8f\x98\xdf\x97\xff\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x86\x00\x46\xa8\x40\x00\x00\xb4\x00\x00\x00\x00\x00\x00\x00\x00\x03\x04\x40\xe0\x00\x01\x51\x80\x00\x00\x38\x40\x00\x00\x00\x00\x20\x01\x06\x38\x08\x07\x02\x1d\x00\x00\x00\x00\x00\x00\x00\x00\x19\x03\x00\x00\x00\x00\x00\x3c\x20\x01\x06\x38\x08\x07\x02\x01\x02\x11\x43\xff\xfe\x5b\x35\x1b\x01\x01\x00\x00\x1c\xd5\x06\x41\x0b\x18\x01\x00\x40\x7e\xd5\xfc\xc9\x69\x05\x3d\x8f\xa3\x7b\xb6\x09\x39\x86\xe2\xfe\x80\x00\x00\x00\x00\x00\x00\x00\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xaf\x96\x81\x88\xe2\xfb\x44\x20\x3d\xa9\xc9\x1b\x07\xde\x9d\x55\x27\x9e\xf7\xdc\xe6\xe2\xd2\x9b\x5c\x9a\x46\x72\x2b\x02\x10\xce\x4d\xc2\x87\xb7\x74\x03\x91\xac\xcd\xc5\x87\x5e\x06\xaf\xc8\x9a\xda\x29\xf9\xe9\x16\x8a\xc6\x97\x62\x76\xbb\x14\xb0\xab\xb7\xfe\x03\x34\x12\x98\x4b\x8e\x77\xba\x2b\x1b\x09\x8f\x6e\xd9\xb3\x59\x68\xb5\x35\xa8\x68\x08\x21\x70\x7f\x65\x6d\xca\xd1\x75\xdd\xc1\xbc\x1c\xc6\xee\x8b\x8c\x74\x3f\xbd\x8b\x8f\xde\x26\xa1\x99\x3b\xb2\x3c\xb6\x6b\xfc\xc5\xa1\x76\xaf\xd5\x07\x02\x62\x71\x6c\x09\x02\x03\x01\x00\x01\x00\x0d\x02\x00\x00\x00\x00\x00\x00\x00\x00\x4f\x17\xed\xe3\x79\xae\x2a\x02\x07\x00\x80\x81\x0a\x0b\x09\x00\x00\x00\x00\x00\x00\x00\x0c\x13\x00\x00\xf8\x55\x0b\xb2\x49\xe1\xd9\x0a\x2a\xe4\x00\xc2\x02\xc1\x8b\xff\x28\xcb\x82\x44\x51\x3c\x43\xd9\x54\xa3\xa3\x88\x03\xc5\x12\xf3\x00\x1f\x8c\x07\x55\x5b\x26\x35\xd6\xfb\x8b\x61\x69\xf2\x28\xb9\x33\x41\xa0\x01\xbb\x71\x37\x03\x02\x52\xb0\xe6\x54\x51\x0c\x50\x2b\xc0\x2a\x49\x11\x1f\x32\x0f\xfe\x0a\x53\x08\xf5\xf9\x10\x2d\x46\x86\x3d\x95\x89\xe2\x24\xc5\x76\x60\x13\x0b\x33\x4a\x1b\xc4\x5d\xef\xa7\x9e\xbf\x7f\x88\x32\xdf\x08\xba\x5b\xac\x52\xa3\xe3\x5f\xc1\x5a\xf0\x36\xfa\x76\x56\x4d\x7e\x80\x72\x39\xd0\x4c\x5f\xca\x24\x06\xa6\x12\x8f\x94\x2f\xe1\x67\xc4\xe6\xc3\xba\x4a\x03\x00\x00\x00\x00" def setUp(self): self.verifier = RAVerifier() def test_checksum(self): checksum = self.verifier._checksum(self.RA_PACKET) self.assertEqual(checksum, b'\x65\x3a')
def setUp(self): self.verifier = RAVerifier()
class MacOSAdapter(object): KEXT_NAME = "net.trustrouter.kext" ACTION_REJECT = 1 ACTION_ACCEPT = 0 def __init__(self, config=None, socket_=None, verifier=None): if socket_ is None: self.socket = socket.socket(socket.PF_SYSTEM, socket.SOCK_STREAM, socket.SYSPROTO_CONTROL) else: self.socket = socket_ if verifier is None: syslog.openlog("TrustRouter") def log(string): syslog.syslog(syslog.LOG_ALERT, string) self.verifier = RAVerifier(log, config) else: self.verifier = verifier def main(self): self.socket.connect(self.KEXT_NAME) while True: packet_id = self._readBytes(struct.calcsize("P")) # Read IPv6 Header (= 40 bytes) packet = self._readBytes(40) scopeid = self._remove_scope_id_from_addrs(packet) # Unmarshal payload length field payload_length = struct.unpack("!H", packet[4:6])[0] packet.extend(self._readBytes(payload_length)) sock = socket.socket( socket.AF_INET6, socket.SOCK_RAW, IPPROTO_ICMPV6) sock.settimeout(2) try: verified_ra = self.verifier.verify(packet, scopeid, sock) except Exception as e: self.verifier.log("Error: %s" % e) # something went wrong during verification verified_ra = False sock.close() if verified_ra: self._send_result(packet_id, self.ACTION_ACCEPT) else: self._send_result(packet_id, self.ACTION_REJECT) def _send_result(self, id, action): result = bytearray(id) result.extend(struct.pack("P", action)) self.socket.send(result) def _readBytes(self, count): result = bytearray() while len(result) != count: result.extend(self.socket.recv(count - len(result))) return result def _remove_scope_id_from_addrs(self, ipv6header): scopeid = 0 if self._is_link_local(ipv6header[8:10]): scopeid = struct.unpack("!H", ipv6header[10:12])[0] ipv6header[10:12] = b"\x00\x00" if self._is_link_local(ipv6header[24:26]): scopeid = struct.unpack("!H", ipv6header[26:28])[0] ipv6header[26:28] = b"\x00\x00" return scopeid def _is_link_local(self, addr): return (addr[0] == 0xfe and addr[1] & 0xc0 == 0x80) or \ (addr[0] == 0xff and (addr[1] & 0x0f == 0x02 or addr[1] & 0x0f == 0x01))
class WindowsAdapter(object): CALLOUT_DRIVER_NAME = "\\\\.\\trustrtr" POINTER_LENGTH = struct.calcsize("P") UNSIGNED_INTEGER_LENGTH = struct.calcsize("I") ACTION_BLOCK = "B" ACTION_PERMIT = "P" def __init__(self, shared_=None, log_fn=print): self.callout = win32file.CreateFile( self.CALLOUT_DRIVER_NAME, win32file.GENERIC_READ | win32file.GENERIC_WRITE, win32file.FILE_SHARE_READ, None, win32file.OPEN_EXISTING, 0, 0) self.log = log_fn if shared_ is None: self.shared = RAVerifier(self.log) else: self.shared = shared_ def read_from_callout_until_success(self): result_code = 1 while result_code != 0: try: result_code, result_buffer = win32file.ReadFile( self.callout, 100000, None) except Exception: #print("Tried ReadFile, got nothing.") pass time.sleep(1) return result_buffer def main(self): result_buffer = self.read_from_callout_until_success() address_byte_array = bytearray(result_buffer[:self.POINTER_LENGTH]) interface_index = bytearray( result_buffer[self.POINTER_LENGTH:self.POINTER_LENGTH + self.UNSIGNED_INTEGER_LENGTH]) packet_byte_array = bytearray( result_buffer[(self.POINTER_LENGTH + self.UNSIGNED_INTEGER_LENGTH):]) interface_index = struct.unpack("@I", interface_index)[0] #for packet_byte in packet_byte_array: # print ("\\x%02x" % packet_byte, end="") result = bytearray() result.extend(address_byte_array) sock = socket.socket(socket.AF_INET6, socket.SOCK_RAW, IPPROTO_ICMPV6) sock.settimeout(2) ''' The CPAs will have the solicited-node multicast address as target. Therefore, we need to join this multicast group. On Mac OS X, this seems to happen automatically. ''' self.join_multicast_group(sock, interface_index) if self.shared.verify(packet_byte_array, interface_index, sock): action = self.ACTION_PERMIT else: action = self.ACTION_BLOCK sock.close() result.extend(struct.pack("c", bytes(action, encoding="ascii"))) win32file.WriteFile(self.callout, result, None) def join_multicast_group(self, sock, interface_index): # Get all IPv6 address info tuples of the host. addr_info_list = [ addr_info[4] for addr_info in socket.getaddrinfo( socket.gethostname(), None, family=socket.AF_INET6) ] # Filter IPv6 address infos by the specified interface index, select only IPv6 address addr_list = [ addr[0] for addr in addr_info_list if addr[3] == interface_index ] for addr in addr_list: # Removes the %-sign if present and everything thereafter. addr = addr.partition("%")[0] # Get the byte representation of the address addr_bytes = IPv6Address(addr).packed # Build the solicited-node multicast address by appending the # last 3 bytes of the unicast address to ff02::1:ff__: mcast_addr_end = addr_bytes[-3:] mcast_addr = b"\xff\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xff" + mcast_addr_end mreq = struct.pack("=16sI", mcast_addr, interface_index) sock.setsockopt(IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, mreq)
class WindowsAdapter(object): CALLOUT_DRIVER_NAME = "\\\\.\\trustrtr" POINTER_LENGTH = struct.calcsize("P") UNSIGNED_INTEGER_LENGTH = struct.calcsize("I") ACTION_BLOCK = "B" ACTION_PERMIT = "P" def __init__(self, shared_=None, log_fn=print): self.callout = win32file.CreateFile( self.CALLOUT_DRIVER_NAME, win32file.GENERIC_READ | win32file.GENERIC_WRITE, win32file.FILE_SHARE_READ, None, win32file.OPEN_EXISTING, 0, 0) self.log = log_fn if shared_ is None: self.shared = RAVerifier(self.log) else: self.shared = shared_ def read_from_callout_until_success(self): result_code = 1 while result_code != 0: try: result_code, result_buffer = win32file.ReadFile( self.callout, 100000, None) except Exception: #print("Tried ReadFile, got nothing.") pass time.sleep(1) return result_buffer def main(self): result_buffer = self.read_from_callout_until_success() address_byte_array = bytearray(result_buffer[:self.POINTER_LENGTH]) interface_index = bytearray(result_buffer[self.POINTER_LENGTH:self.POINTER_LENGTH + self.UNSIGNED_INTEGER_LENGTH]) packet_byte_array = bytearray(result_buffer[(self.POINTER_LENGTH + self.UNSIGNED_INTEGER_LENGTH):]) interface_index = struct.unpack("@I", interface_index)[0] #for packet_byte in packet_byte_array: # print ("\\x%02x" % packet_byte, end="") result = bytearray() result.extend(address_byte_array) sock = socket.socket( socket.AF_INET6, socket.SOCK_RAW, IPPROTO_ICMPV6) sock.settimeout(2) ''' The CPAs will have the solicited-node multicast address as target. Therefore, we need to join this multicast group. On Mac OS X, this seems to happen automatically. ''' self.join_multicast_group(sock, interface_index) if self.shared.verify(packet_byte_array, interface_index, sock): action = self.ACTION_PERMIT else: action = self.ACTION_BLOCK sock.close() result.extend(struct.pack("c", bytes(action, encoding="ascii"))) win32file.WriteFile(self.callout, result, None) def join_multicast_group(self, sock, interface_index): # Get all IPv6 address info tuples of the host. addr_info_list = [addr_info[4] for addr_info in socket.getaddrinfo(socket.gethostname(), None, family=socket.AF_INET6)] # Filter IPv6 address infos by the specified interface index, select only IPv6 address addr_list = [addr[0] for addr in addr_info_list if addr[3] == interface_index] for addr in addr_list: # Removes the %-sign if present and everything thereafter. addr = addr.partition("%")[0] # Get the byte representation of the address addr_bytes = IPv6Address(addr).packed # Build the solicited-node multicast address by appending the # last 3 bytes of the unicast address to ff02::1:ff__: mcast_addr_end = addr_bytes[-3:] mcast_addr = b"\xff\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xff" + mcast_addr_end mreq = struct.pack("=16sI", mcast_addr, interface_index) sock.setsockopt(IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, mreq)
class MacOSAdapter(object): KEXT_NAME = "net.trustrouter.kext" ACTION_REJECT = 1 ACTION_ACCEPT = 0 def __init__(self, config=None, socket_=None, verifier=None): if socket_ is None: self.socket = socket.socket(socket.PF_SYSTEM, socket.SOCK_STREAM, socket.SYSPROTO_CONTROL) else: self.socket = socket_ if verifier is None: syslog.openlog("TrustRouter") def log(string): syslog.syslog(syslog.LOG_ALERT, string) self.verifier = RAVerifier(log, config) else: self.verifier = verifier def main(self): self.socket.connect(self.KEXT_NAME) while True: packet_id = self._readBytes(struct.calcsize("P")) # Read IPv6 Header (= 40 bytes) packet = self._readBytes(40) scopeid = self._remove_scope_id_from_addrs(packet) # Unmarshal payload length field payload_length = struct.unpack("!H", packet[4:6])[0] packet.extend(self._readBytes(payload_length)) sock = socket.socket(socket.AF_INET6, socket.SOCK_RAW, IPPROTO_ICMPV6) sock.settimeout(2) try: verified_ra = self.verifier.verify(packet, scopeid, sock) except Exception as e: self.verifier.log("Error: %s" % e) # something went wrong during verification verified_ra = False sock.close() if verified_ra: self._send_result(packet_id, self.ACTION_ACCEPT) else: self._send_result(packet_id, self.ACTION_REJECT) def _send_result(self, id, action): result = bytearray(id) result.extend(struct.pack("P", action)) self.socket.send(result) def _readBytes(self, count): result = bytearray() while len(result) != count: result.extend(self.socket.recv(count - len(result))) return result def _remove_scope_id_from_addrs(self, ipv6header): scopeid = 0 if self._is_link_local(ipv6header[8:10]): scopeid = struct.unpack("!H", ipv6header[10:12])[0] ipv6header[10:12] = b"\x00\x00" if self._is_link_local(ipv6header[24:26]): scopeid = struct.unpack("!H", ipv6header[26:28])[0] ipv6header[26:28] = b"\x00\x00" return scopeid def _is_link_local(self, addr): return (addr[0] == 0xfe and addr[1] & 0xc0 == 0x80) or \ (addr[0] == 0xff and (addr[1] & 0x0f == 0x02 or addr[1] & 0x0f == 0x01))
from trustrouter.core import RAVerifier packet = b"\x60\x00\x00\x00\x01\xc8\x3a\xff\xfe\x80\x00\x00\x00\x00\x00\x00\x2c\xf2\x7e\xf7\x8f\x98\xdf\x97\xff\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x86\x00\x10\xf1\x40\x00\x00\xb4\x00\x00\x00\x00\x00\x00\x00\x00\x03\x04\x40\xe0\x00\x01\x51\x80\x00\x00\x38\x40\x00\x00\x00\x00\x20\x01\x06\x38\x08\x07\x02\x1d\x00\x00\x00\x00\x00\x00\x00\x00\x19\x03\x00\x00\x00\x00\x00\x3c\x20\x01\x06\x38\x08\x07\x02\x01\x02\x11\x43\xff\xfe\x5b\x35\x1b\x01\x01\x00\x00\x1c\xd5\x06\x41\x0b\x18\x01\x00\x40\x7e\xd5\xfc\xc9\x69\x05\x3d\x8f\xa3\x7b\xb6\x09\x39\x86\xe2\xfe\x80\x00\x00\x00\x00\x00\x00\x00\x30\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d\x00\x30\x81\x89\x02\x81\x81\x00\xaf\x96\x81\x88\xe2\xfb\x44\x20\x3d\xa9\xc9\x1b\x07\xde\x9d\x55\x27\x9e\xf7\xdc\xe6\xe2\xd2\x9b\x5c\x9a\x46\x72\x2b\x02\x10\xce\x4d\xc2\x87\xb7\x74\x03\x91\xac\xcd\xc5\x87\x5e\x06\xaf\xc8\x9a\xda\x29\xf9\xe9\x16\x8a\xc6\x97\x62\x76\xbb\x14\xb0\xab\xb7\xfe\x03\x34\x12\x98\x4b\x8e\x77\xba\x2b\x1b\x09\x8f\x6e\xd9\xb3\x59\x68\xb5\x35\xa8\x68\x08\x21\x70\x7f\x65\x6d\xca\xd1\x75\xdd\xc1\xbc\x1c\xc6\xee\x8b\x8c\x74\x3f\xbd\x8b\x8f\xde\x26\xa1\x99\x3b\xb2\x3c\xb6\x6b\xfc\xc5\xa1\x76\xaf\xd5\x07\x02\x62\x71\x6c\x09\x02\x03\x01\x00\x01\x00\x0d\x02\x00\x00\x00\x00\x00\x00\x00\x00\x4f\x1e\x90\x6e\xd0\x74\x2a\x02\x07\x00\x80\x81\x0a\x0b\x09\x00\x00\x00\x00\x00\x00\x00\x0c\x13\x00\x00\xf8\x55\x0b\xb2\x49\xe1\xd9\x0a\x2a\xe4\x00\xc2\x02\xc1\x8b\xff\x09\x24\x31\xdf\xb5\x66\xd2\x00\x74\x82\x0c\x84\x8d\xfa\x39\x33\x9c\x80\xfb\x7d\x2c\x10\x68\x7f\x4b\x75\x28\x28\x5a\x41\x39\x44\x23\x6f\x36\xc1\x42\x9a\x86\x3c\xcc\x25\xfc\xd7\x16\x66\x0a\x42\x46\xe5\x0b\x9f\x8f\x09\xf3\xde\x43\x58\xdc\x2b\xa7\x89\xbb\xa6\xf9\x98\x4b\xb2\x45\x28\x44\xd2\xd2\xa3\xaf\x85\x16\xf2\xca\x3f\x81\x7a\x99\xea\x7a\x39\xc8\xe5\xc1\xbc\x65\xf4\x5e\xa6\x88\x4b\x7a\x34\x55\x72\xd0\xbe\x2d\x51\xd2\xd9\x42\x2b\x68\x32\x77\x83\xc8\xbc\x6c\xf8\x79\x68\xcb\xed\x90\x84\x45\x20\xc5\x24\x60\xcf\x00\x00\x00\x00" verifier = RAVerifier() result = verifier.verify(packet, 4) print(result)