From c440609ca7fb8b85d83d528526b3f02c1a63376d Mon Sep 17 00:00:00 2001 From: RPRX <63339210+rprx@users.noreply.github.com> Date: Mon, 26 Apr 2021 06:19:51 +0000 Subject: [PATCH] Add local response to ICMP PING requests (IPv4 & IPv6) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://github.com/2dust/v2rayNG/issues/1027 高效实现,十分感谢 @yuhan6665 协助测试 --- misc/ipv4_proto.h | 1 + misc/ipv6_proto.h | 1 + tun2socks/tun2socks.c | 42 ++++++++++++++++++++++++++++++++++++++---- 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/misc/ipv4_proto.h b/misc/ipv4_proto.h index fea726015..ba59b2315 100644 --- a/misc/ipv4_proto.h +++ b/misc/ipv4_proto.h @@ -42,6 +42,7 @@ #include #include +#define IPV4_PROTOCOL_ICMP 1 #define IPV4_PROTOCOL_IGMP 2 #define IPV4_PROTOCOL_UDP 17 diff --git a/misc/ipv6_proto.h b/misc/ipv6_proto.h index b25554138..0b03b3807 100644 --- a/misc/ipv6_proto.h +++ b/misc/ipv6_proto.h @@ -39,6 +39,7 @@ #define IPV6_NEXT_IGMP 2 #define IPV6_NEXT_UDP 17 +#define IPV6_NEXT_ICMP 58 B_START_PACKED struct ipv6_header { diff --git a/tun2socks/tun2socks.c b/tun2socks/tun2socks.c index b4352bcf9..f154614fc 100644 --- a/tun2socks/tun2socks.c +++ b/tun2socks/tun2socks.c @@ -1428,10 +1428,27 @@ int process_device_udp_packet (uint8_t *data, int data_len) switch (ip_version) { case 4: { - // ignore non-UDP packets - if (data_len < sizeof(struct ipv4_header) || data[offsetof(struct ipv4_header, protocol)] != IPV4_PROTOCOL_UDP) { + // ignore non-UDP-nor-ICMP packets + if (data_len < sizeof(struct ipv4_header)) { goto fail; } + switch (data[offsetof(struct ipv4_header, protocol)]) { + case IPV4_PROTOCOL_UDP: break; + case IPV4_PROTOCOL_ICMP: { + if (data[0] == 69 && data_len >= 28 && data[20] == 8 && data[21] == 0) { // ping + uint8_t ip_source[4]; + memcpy(ip_source, &data[12], 4); + memcpy(&data[12], &data[16], 4); + memcpy(&data[16], ip_source, 4); + data[20] = 0; // response + data[22] += 8; // checksum + if (data[22] < 8) data[23] += 1; + BTap_Send(&device, data, data_len); + } + return 1; + } + default: goto fail; + } // parse IPv4 header struct ipv4_header ipv4_header; @@ -1483,10 +1500,27 @@ int process_device_udp_packet (uint8_t *data, int data_len) goto fail; } - // ignore non-UDP packets - if (data_len < sizeof(struct ipv6_header) || data[offsetof(struct ipv6_header, next_header)] != IPV6_NEXT_UDP) { + // ignore non-UDP-nor-ICMP packets + if (data_len < sizeof(struct ipv6_header)) { goto fail; } + switch (data[offsetof(struct ipv6_header, next_header)]) { + case IPV6_NEXT_UDP: break; + case IPV6_NEXT_ICMP: { + if (data_len >= 48 && data[40] == 128 && data[41] == 0) { // ping6 + uint8_t ip_source[16]; + memcpy(ip_source, &data[8], 16); + memcpy(&data[8], &data[24], 16); + memcpy(&data[24], ip_source, 16); + data[40] = 129; // response + data[42] -= 1; // checksum + if (data[42] == 255) data[43] -= 1; + BTap_Send(&device, data, data_len); + } + return 1; + } + default: goto fail; + } // parse IPv6 header struct ipv6_header ipv6_header;