Skip to content

Commit

Permalink
Add local response to ICMP PING requests (IPv4 & IPv6)
Browse files Browse the repository at this point in the history
2dust/v2rayNG#1027

高效实现,十分感谢 @yuhan6665 协助测试
  • Loading branch information
RPRX authored Apr 26, 2021
1 parent fb01eb9 commit c440609
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 4 deletions.
1 change: 1 addition & 0 deletions misc/ipv4_proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include <misc/packed.h>
#include <misc/read_write_int.h>

#define IPV4_PROTOCOL_ICMP 1
#define IPV4_PROTOCOL_IGMP 2
#define IPV4_PROTOCOL_UDP 17

Expand Down
1 change: 1 addition & 0 deletions misc/ipv6_proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
42 changes: 38 additions & 4 deletions tun2socks/tun2socks.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit c440609

Please sign in to comment.