|
|
|
|
@ -159,24 +159,27 @@ static int tcp_proxy_client_handle_non_tcp(struct tcp_proxy_client* p, uint8_t*
|
|
|
|
|
if (len < 20) return 0; |
|
|
|
|
uint8_t ip_ver = (buf[0] >> 4) & 0xF; |
|
|
|
|
if (ip_ver != 4) return 0; |
|
|
|
|
uint16_t ihl = (buf[0] & 15) * 4; |
|
|
|
|
if (ihl < 20 || len < ihl + 8u) return 0; |
|
|
|
|
uint8_t* transport = buf + ihl; |
|
|
|
|
uint8_t proto = buf[9]; |
|
|
|
|
if (proto == IPPROTO_UDP) { |
|
|
|
|
if (len < 28) return 0; |
|
|
|
|
uint32_t src_ip, dst_ip; uint16_t src_port, dst_port; |
|
|
|
|
memcpy(&src_ip, buf + 12, 4); memcpy(&dst_ip, buf + 16, 4); |
|
|
|
|
memcpy(&src_port, buf + 20, 2); memcpy(&dst_port, buf + 22, 2); |
|
|
|
|
udp_proxy_send_to_exit(p->inst, p->via_node_id, src_ip, src_port, dst_ip, dst_port, buf + 28, len - 28); |
|
|
|
|
memcpy(&src_port, transport, 2); memcpy(&dst_port, transport + 2, 2); |
|
|
|
|
udp_proxy_send_to_exit(p->inst, p->via_node_id, src_ip, src_port, dst_ip, dst_port, transport + 8, len - ihl - 8); |
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
|
if (proto == IPPROTO_ICMP) { |
|
|
|
|
if (len < 28) return 0; |
|
|
|
|
uint8_t icmp_type = buf[20]; |
|
|
|
|
uint8_t icmp_type = transport[0]; |
|
|
|
|
if (icmp_type != 8) return 0; |
|
|
|
|
uint32_t src_ip, dst_ip; |
|
|
|
|
memcpy(&src_ip, buf + 12, 4); memcpy(&dst_ip, buf + 16, 4); |
|
|
|
|
uint16_t icmp_id, icmp_seq; |
|
|
|
|
memcpy(&icmp_id, buf + 24, 2); memcpy(&icmp_seq, buf + 26, 2); |
|
|
|
|
icmp_proxy_send_to_exit(p->inst, p->via_node_id, dst_ip, src_ip, icmp_id, icmp_seq, buf + 28, len - 28); |
|
|
|
|
memcpy(&icmp_id, transport + 4, 2); memcpy(&icmp_seq, transport + 6, 2); |
|
|
|
|
icmp_proxy_send_to_exit(p->inst, p->via_node_id, dst_ip, src_ip, icmp_id, icmp_seq, transport + 8, len - ihl - 8); |
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
|
return 0; |
|
|
|
|
@ -509,13 +512,19 @@ static void tcp_proxy_client_tun_input(struct ll_queue* q, void* arg) {
|
|
|
|
|
if (!entry) return; |
|
|
|
|
if (entry->dgram && entry->len > 1) { |
|
|
|
|
uint8_t* ip = entry->dgram + 1; size_t len = entry->len - 1; |
|
|
|
|
if (len > 20 && len <= 2000) { |
|
|
|
|
if (!tcp_proxy_client_handle_non_tcp(p, ip, len)) { |
|
|
|
|
uint16_t ihl = len ? (ip[0] & 15) * 4 : 0; |
|
|
|
|
uint16_t total = len >= 4 ? ((uint16_t)ip[2] << 8) | ip[3] : 0; |
|
|
|
|
if (len < 20 || (ip[0] >> 4) != 4 || ihl < 20 || total < ihl || total > len) { |
|
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_PROXY, "proxy TUN: invalid IPv4 packet len=%zu ihl=%u total=%u", len, ihl, total); |
|
|
|
|
} else if ((ip[6] & 0x3f) || ip[7]) { |
|
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_PROXY, "proxy TUN: fragmented IPv4 packet unsupported flags=%02x%02x", ip[6], ip[7]); |
|
|
|
|
} else { |
|
|
|
|
if (!tcp_proxy_client_handle_non_tcp(p, ip, total)) { |
|
|
|
|
uint8_t proto = ip[9]; |
|
|
|
|
if (proto == IPPROTO_TCP) { |
|
|
|
|
uint16_t ip_hdr_len = (ip[0] & 0x0F) * 4; |
|
|
|
|
uint16_t ip_total = ((uint16_t)ip[2] << 8) | ip[3]; |
|
|
|
|
if (ip_hdr_len >= 20 && ip_total >= ip_hdr_len && len >= ip_total) { |
|
|
|
|
if (ip_hdr_len >= 20 && ip_total >= ip_hdr_len + 20 && len >= ip_total) { |
|
|
|
|
uint16_t dport_net; memcpy(&dport_net, ip + ip_hdr_len + 2, 2); |
|
|
|
|
tcp_proxy_client_ensure_outbound_listen(p, dport_net); |
|
|
|
|
uint32_t src_ip, dst_ip; |
|
|
|
|
|