diff options
author | Ido Barnea <ibarnea@cisco.com> | 2016-07-06 11:04:52 +0300 |
---|---|---|
committer | Ido Barnea <ibarnea@cisco.com> | 2016-07-12 16:06:02 +0300 |
commit | cc5cc5631e9df4ef0eee9c26705208dfcf035e8c (patch) | |
tree | cf43869ae348d02f7b3c1551e88d07d8a3f28a9d /src/nat_check.cpp | |
parent | c19193cff9413a03dd85cc9facda0c28b28d37c2 (diff) |
NAT seq num randomization working version - Missing some functionality
Diffstat (limited to 'src/nat_check.cpp')
-rwxr-xr-x | src/nat_check.cpp | 78 |
1 files changed, 68 insertions, 10 deletions
diff --git a/src/nat_check.cpp b/src/nat_check.cpp index 7e224430..c7262e50 100755 --- a/src/nat_check.cpp +++ b/src/nat_check.cpp @@ -41,7 +41,8 @@ void CGenNodeNatInfo::dump(FILE *fd){ int i; for (i=0; i<m_cnt; i++) { CNatFlowInfo * lp=&m_data[i]; - fprintf (fd," id:%d , external ip:%08x:%x , ex_port: %04x , fid: %d \n",i,lp->m_external_ip,lp->m_external_ip_server,lp->m_external_port,lp->m_fid); + fprintf (fd," id:%d , external ip:%08x , ex_port: %04x , TCP seq:%x fid: %d \n" + , i, lp->m_external_ip, lp->m_external_port, lp->m_tcp_seq, lp->m_fid); } } @@ -51,6 +52,28 @@ void CGenNodeNatInfo::init(){ m_cnt=0; } +bool CNatCheckFlowTableMap::find(uint64_t key, uint32 &val) { + nat_check_flow_map_t::iterator iter; + iter = m_map.find(key); + if (iter != m_map.end() ) { + val = (*iter).second; + return true; + }else{ + return false; + } +} + +void CNatCheckFlowTableMap::dump(FILE *fd) { + nat_check_flow_map_iter_t it; + uint32_t val; + uint64_t key; + + for (it = m_map.begin(); it != m_map.end(); it++) { + val = it->second; + key = it->first; + fprintf(fd, "%lx->%x\n", key, val); + } +} void CNatStats::reset(){ m_total_rx=0; @@ -147,14 +170,17 @@ void CNatRxManager::get_info_from_tcp_ack(uint32_t tcp_ack, uint32_t &fid, uint8 * option - pointer to our proprietary NAT info IP option. * If it is NULL, the NAT info is in the TCP ACK number * ipv4 - pointer to ipv4 header to extract info from. + * is_first - Is this the first packet of the flow or second. To handle firewalls that do + * TCP seq randomization on the server->client side, we also look at the second + * packet of the flow (SYN+ACK), and extract its seq num. */ -void CNatRxManager::handle_packet_ipv4(CNatOption *option, IPHeader *ipv4) { +void CNatRxManager::handle_packet_ipv4(CNatOption *option, IPHeader *ipv4, bool is_first) { CNatPerThreadInfo * thread_info; uint32_t fid=0; + uint32_t tcp_seq; /* Extract info from the packet ! */ uint32_t ext_ip = ipv4->getSourceIp(); - uint32_t ext_ip_server = ipv4->getDestIp(); uint8_t proto = ipv4->getProtocol(); /* must be TCP/UDP this is the only supported proto */ if (!( (proto==6) || (proto==17) )){ @@ -165,21 +191,49 @@ void CNatRxManager::handle_packet_ipv4(CNatOption *option, IPHeader *ipv4) { TCPHeader *tcp = (TCPHeader *) (((char *)ipv4)+ ipv4->getHeaderLength()); uint16_t ext_port = tcp->getSourcePort(); + tcp_seq = tcp->getSeqNumber(); + if (option) { thread_info = get_thread_info(option->get_thread_id()); fid = option->get_fid(); } else { - uint8_t thread_id; - get_info_from_tcp_ack(tcp->getAckNumber(), fid, thread_id); - thread_info = get_thread_info(thread_id); + uint8_t thread_id; + + if (is_first) { + uint32_t tcp_ack = tcp->getAckNumber(); + get_info_from_tcp_ack(tcp_ack, fid, thread_id); + thread_info = get_thread_info(thread_id); + if (CGlobalInfo::is_learn_mode(CParserOption::LEARN_MODE_TCP_ACK)) { + uint32_t dst_ip = ipv4->getDestIp(); + uint16_t dst_port = tcp->getDestPort(); + uint64_t map_key = (dst_ip << 16) + dst_port; + m_fm.insert(map_key, tcp_ack); + } + } else { + uint32_t val; + // server->client packet. IP/port reversed in regard to first SYN packet + uint64_t map_key = (ext_ip << 16) + ext_port; + + if (m_fm.find(map_key, val)) { + get_info_from_tcp_ack(val, fid, thread_id); + thread_info = get_thread_info(thread_id); + m_fm.erase(map_key); + } else { + thread_info = 0; + // ??? Handle error + // ??? handle aging of flow info + } + } } + if (unlikely(!thread_info)) { return; } #ifdef NAT_TRACE_ - printf("rx msg ext ip : %08x:%08x ext port : %04x flow_id : %d \n",ext_ip,ext_ip_server,ext_port, fid); + printf("rx msg ext ip: %08x ext port: %04x TCP Seq: %08x flow_id : %d (%s) \n", ext_ip, ext_port, tcp_seq, fid + , is_first ? "first":"second"); #endif CGenNodeNatInfo * node=thread_info->m_cur_nat_msg; @@ -194,9 +248,13 @@ void CNatRxManager::handle_packet_ipv4(CNatOption *option, IPHeader *ipv4) { CNatFlowInfo * msg=node->get_next_msg(); /* fill the message */ - msg->m_external_ip = ext_ip; - msg->m_external_ip_server = ext_ip_server; - msg->m_external_port = ext_port; + if (is_first) { + msg->m_external_ip = ext_ip; + msg->m_external_port = ext_port; + } else { + msg->m_external_port = TCPHeader::TCP_INVALID_PORT; + } + msg->m_tcp_seq = tcp_seq; msg->m_fid = fid; msg->m_pad = 0xee; |