def _establish_conn(self, dport): seq_no = random.randint(0, 2**32 - 1) eph_port = random.randint(30000, 60000) self._reset_conn(eph_port, dport, seq_no) # create connection to the VIP on the alt host, which will accept the SYN syn = \ IP(dst=self.ALT_HOST) / \ UDP(sport=12345, dport=19523) / \ GLBGUE(private_data=GLBGUEChainedRouting(hops=[])) / \ IPv6(src=self.SELF_HOST_V6, dst=self.VIP) / \ TCP(sport=eph_port, dport=dport, flags='S', seq=seq_no) # retrieve the SYN-ACK syn_ack = self._sendrecv6(syn, lfilter=self._match_tuple( self.VIP, self.SELF_HOST_V6, dport, eph_port)) seq_no = syn_ack.ack ack_no = syn_ack.seq + 1 ack = \ IP(dst=self.ALT_HOST) / \ UDP(sport=12345, dport=19523) / \ GLBGUE(private_data=GLBGUEChainedRouting(hops=[])) / \ IPv6(src=self.SELF_HOST_V6, dst=self.VIP) / \ TCP(sport=eph_port, dport=dport, flags='A', seq=seq_no, ack=ack_no) send(ack) return (eph_port, seq_no, ack_no)
def test_03_accepted_on_secondary_chain_host(self): eph_port = random.randint(30000, 60000) # force RST for this tuple rst = \ IP(dst=self.ALT_HOST) / \ UDP(sport=12345, dport=19523) / \ GLBGUE(private_data=GLBGUEChainedRouting(hops=[])) / \ IPv6(src=self.SELF_HOST_V6, dst=self.VIP) / \ TCP(sport=eph_port, dport=22, flags='R', seq=1234) send(rst) # create connection to the VIP on the alt host, which will accept the SYN syn = \ IP(dst=self.ALT_HOST) / \ UDP(sport=12345, dport=19523) / \ GLBGUE(private_data=GLBGUEChainedRouting(hops=[])) / \ IPv6(src=self.SELF_HOST_V6, dst=self.VIP) / \ TCP(sport=eph_port, dport=22, flags='S', seq=1234) # retrieve the SYN-ACK resp_ip = self._sendrecv6(syn, filter='ip6 host {} and port 22'.format( self.VIP)) assert isinstance(resp_ip, IPv6) assert_equals(resp_ip.src, self.VIP) assert_equals(resp_ip.dst, self.SELF_HOST_V6) resp_tcp = resp_ip.payload assert isinstance(resp_tcp, TCP) assert_equals(resp_tcp.sport, 22) assert_equals(resp_tcp.dport, eph_port) assert_equals(resp_tcp.flags, 'SA') assert_equals(resp_tcp.ack, syn.seq + 1) syn_ack = resp_ip # now send an ACK to the primary proxy host, it should get accepted on the second hop ack = \ IP(dst=self.PROXY_HOST) / \ UDP(sport=12345, dport=19523) / \ GLBGUE(private_data=GLBGUEChainedRouting(hops=[self.ALT_HOST, self.SELF_HOST])) / \ IPv6(src=self.SELF_HOST_V6, dst=self.VIP) / \ TCP(sport=eph_port, dport=22, flags='A', seq=syn_ack.ack, ack=syn_ack.seq + 1) # ensure we get a PSH from the host, since SSH should send us the banner resp_ip = self._sendrecv6(ack, filter='ip6 host {} and port 22'.format( self.VIP)) assert isinstance(resp_ip, IPv6) assert_equals(resp_ip.src, self.VIP) assert_equals(resp_ip.dst, self.SELF_HOST_V6) resp_tcp = resp_ip.payload assert isinstance(resp_tcp, TCP) assert_equals(resp_tcp.sport, 22) assert_equals(resp_tcp.dport, eph_port) assert_equals(resp_tcp.flags, 'PA')
def test_02_unknown_redirected_through_chain(self): pkt = \ IP(dst=self.PROXY_HOST) / \ UDP(sport=12345, dport=19523) / \ GLBGUE(private_data=GLBGUEChainedRouting(hops=[self.ALT_HOST, self.SELF_HOST])) / \ IP(src=self.SELF_HOST, dst=self.VIP) / \ TCP(sport=9999, dport=22, flags='A') # expect the packet to arrive back to us as a FOU packet since nobody knew about the connection # should arrive from the last host in the chain that wasn't us. resp_ip = self._sendrecv4( pkt, filter='host {} and udp and port 19523'.format(self.ALT_HOST)) assert isinstance(resp_ip, IP) assert_equals( resp_ip.src, self.ALT_HOST) # outer FOU will come from penultimate hop assert_equals(resp_ip.dst, self.SELF_HOST) resp_fou = resp_ip.payload assert isinstance(resp_fou, UDP) assert_equals(resp_fou.sport, 12345) assert_equals(resp_fou.dport, 19523) resp_gue = resp_fou.payload assert isinstance(resp_gue, GLBGUE) resp_inner_ip = resp_gue.payload assert isinstance(resp_inner_ip, IP) assert_equals(resp_inner_ip.src, self.SELF_HOST) assert_equals(resp_inner_ip.dst, self.VIP) resp_inner_tcp = resp_inner_ip.payload assert isinstance(resp_inner_tcp, TCP) assert_equals(resp_inner_tcp.sport, 9999) assert_equals(resp_inner_tcp.dport, 22)
def _reset_conn(self, sport, dport, seq): rst = \ IP(dst=self.ALT_HOST) / \ UDP(sport=12345, dport=19523) / \ GLBGUE(private_data=GLBGUEChainedRouting(hops=[])) / \ IPv6(src=self.SELF_HOST_V6, dst=self.VIP) / \ TCP(sport=sport, dport=dport, flags='R', seq=seq) send(rst)
def test_00_icmp_accepted(self): for dst in [self.PROXY_HOST, self.ALT_HOST]: pkt = \ IP(dst=dst) / \ UDP(sport=12345, dport=19523) / \ GLBGUE(private_data=GLBGUEChainedRouting(hops=[self.ALT_HOST])) / \ IPv6(src=self.SELF_HOST_V6, dst=self.V4_TO_V6[dst]) / \ ICMPv6EchoRequest() print repr(pkt) # expect a ICMP echo response back from self.PROXY_HOST (decapsulated) resp_ip = self._sendrecv6(pkt, lfilter=lambda p: isinstance(p, IPv6) and isinstance(p.payload, ICMPv6EchoReply)) assert isinstance(resp_ip, IPv6) assert_equals(resp_ip.src, self.V4_TO_V6[dst]) assert_equals(resp_ip.dst, self.SELF_HOST_V6) resp_icmp = resp_ip.payload assert isinstance(resp_icmp, ICMPv6EchoReply)
def test_01_syn_accepted(self): pkt = \ IP(dst=self.PROXY_HOST) / \ UDP(sport=12345, dport=19523) / \ GLBGUE(private_data=GLBGUEChainedRouting(hops=[self.ALT_HOST])) / \ IPv6(src=self.SELF_HOST_V6, dst=self.V4_TO_V6[self.PROXY_HOST]) / \ TCP(sport=123, dport=22, flags='S') # expect a SYN-ACK back from self.PROXY_HOST (decapsulated) resp_ip = self._sendrecv6(pkt, filter='host {} and port 22'.format( self.V4_TO_V6[self.PROXY_HOST])) assert isinstance(resp_ip, IPv6) assert_equals(resp_ip.src, self.V4_TO_V6[self.PROXY_HOST]) assert_equals(resp_ip.dst, self.SELF_HOST_V6) resp_tcp = resp_ip.payload assert isinstance(resp_tcp, TCP) assert_equals(resp_tcp.sport, 22) assert_equals(resp_tcp.dport, 123) assert_equals(resp_tcp.flags, 'SA')
def test_00_icmp_accepted(self): for dst in [self.PROXY_HOST, self.ALT_HOST]: pkt = \ IP(dst=dst) / \ UDP(sport=12345, dport=19523) / \ GLBGUE(private_data=GLBGUEChainedRouting(hops=[self.ALT_HOST])) / \ IP(src=self.SELF_HOST, dst=dst) / \ ICMP(type=8, code=0) # echo request # expect a ICMP echo response back from self.PROXY_HOST (decapsulated) resp_ip = self._sendrecv4(pkt, filter='host {} and icmp'.format(dst)) print repr(resp_ip) assert isinstance(resp_ip, IP) assert_equals(resp_ip.src, dst) assert_equals(resp_ip.dst, self.SELF_HOST) resp_icmp = resp_ip.payload assert isinstance(resp_icmp, ICMP) assert_equals(resp_icmp.type, 0) # echo reply assert_equals(resp_icmp.code, 0)
def test_04_icmp_packet_too_big(self): # Establish full connection, since ICMP is handled differently for # sockets which haven't completed the full 3-way handshake (aka TCP_NEW_SYN_RECV). (eph_port, seq, ack) = self._establish_conn(dport=80) # send a Packet Too Big message via PROXY from ROUTER, which # should end up on the alt host # note that we end on SELF_HOST so it doesn't 'default accept' it pkt = \ IP(dst=self.PROXY_HOST) / \ UDP(sport=12345, dport=19523) / \ GLBGUE(private_data=GLBGUEChainedRouting(hops=[self.ALT_HOST, self.SELF_HOST])) / \ IP(src=self.ROUTER, dst=self.VIP) / \ ICMP(type=3, code=4, nexthopmtu=800) / \ IP(src=self.VIP, dst=self.SELF_HOST) / \ TCP(sport=80, dport=eph_port, seq=ack, ack=seq) alt_host_stream = RemoteSnoop(self.ALT_HOST, remote_iface='tunl0', remote_type=ETH_P_IP) send(pkt) rem_ip = alt_host_stream.recv(lambda pkt: pkt.src == self.ROUTER) # ensure the remote host (ALT_HOST) received the inner packet through the first (failed) hop assert isinstance(rem_ip, IP) assert_equals(rem_ip.src, self.ROUTER) assert_equals(rem_ip.dst, self.VIP) rem_icmp = rem_ip.payload assert isinstance(rem_icmp, ICMP) assert_equals(rem_icmp.type, 3) assert_equals(rem_icmp.code, 4) assert_equals(rem_icmp.nexthopmtu, 800) rem_ipip = rem_icmp.payload assert isinstance(rem_ipip, IP) assert_equals(rem_ipip.src, self.VIP) assert_equals(rem_ipip.dst, self.SELF_HOST) assert_equals(rem_ipip.sport, 80) assert_equals(rem_ipip.dport, eph_port)