Skip to content

Commit 86acf72

Browse files
committed
only adjust tcp & udp when ip frag offset == 0
1 parent 9313d57 commit 86acf72

File tree

1 file changed

+34
-28
lines changed

1 file changed

+34
-28
lines changed

src/nat.c

+34-28
Original file line numberDiff line numberDiff line change
@@ -171,21 +171,24 @@ int nat_fix_upstream(nat_ctx_t *ctx, unsigned char *buf, size_t buflen,
171171
acc = client->input_tun_ip - iphdr->saddr;
172172
ADJUST_CHECKSUM(acc, iphdr->checksum);
173173

174-
void *ip_payload = buf + SHADOWVPN_USERTOKEN_LEN + iphdr_len;
175-
if (iphdr->proto == IPPROTO_TCP) {
176-
if (buflen < iphdr_len + 20) {
177-
errf("nat: tcp packet too short");
178-
return -1;
174+
if (0 == (iphdr->frag & htons(0x1fff))) {
175+
// only adjust tcp & udp when frag offset == 0
176+
void *ip_payload = buf + SHADOWVPN_USERTOKEN_LEN + iphdr_len;
177+
if (iphdr->proto == IPPROTO_TCP) {
178+
if (buflen < iphdr_len + 20) {
179+
errf("nat: tcp packet too short");
180+
return -1;
181+
}
182+
tcp_hdr_t *tcphdr = ip_payload;
183+
ADJUST_CHECKSUM(acc, tcphdr->checksum);
184+
} else if (iphdr->proto == IPPROTO_UDP) {
185+
if (buflen < iphdr_len + 8) {
186+
errf("nat: udp packet too short");
187+
return -1;
188+
}
189+
udp_hdr_t *udphdr = ip_payload;
190+
ADJUST_CHECKSUM(acc, udphdr->checksum);
179191
}
180-
tcp_hdr_t *tcphdr = ip_payload;
181-
ADJUST_CHECKSUM(acc, tcphdr->checksum);
182-
} else if (iphdr->proto == IPPROTO_UDP) {
183-
if (buflen < iphdr_len + 8) {
184-
errf("nat: udp packet too short");
185-
return -1;
186-
}
187-
udp_hdr_t *udphdr = ip_payload;
188-
ADJUST_CHECKSUM(acc, udphdr->checksum);
189192
}
190193
return 0;
191194
}
@@ -233,21 +236,24 @@ int nat_fix_downstream(nat_ctx_t *ctx, unsigned char *buf, size_t buflen,
233236

234237
ADJUST_CHECKSUM(acc, iphdr->checksum);
235238

236-
void *ip_payload = buf + SHADOWVPN_USERTOKEN_LEN + iphdr_len;
237-
if (iphdr->proto == IPPROTO_TCP) {
238-
if (buflen < iphdr_len + 20) {
239-
errf("nat: tcp packet too short");
240-
return -1;
241-
}
242-
tcp_hdr_t *tcphdr = ip_payload;
243-
ADJUST_CHECKSUM(acc, tcphdr->checksum);
244-
} else if (iphdr->proto == IPPROTO_UDP) {
245-
if (buflen < iphdr_len + 8) {
246-
errf("nat: udp packet too short");
247-
return -1;
239+
if (0 == (iphdr->frag & htons(0x1fff))) {
240+
// only adjust tcp & udp when frag offset == 0
241+
void *ip_payload = buf + SHADOWVPN_USERTOKEN_LEN + iphdr_len;
242+
if (iphdr->proto == IPPROTO_TCP) {
243+
if (buflen < iphdr_len + 20) {
244+
errf("nat: tcp packet too short");
245+
return -1;
246+
}
247+
tcp_hdr_t *tcphdr = ip_payload;
248+
ADJUST_CHECKSUM(acc, tcphdr->checksum);
249+
} else if (iphdr->proto == IPPROTO_UDP) {
250+
if (buflen < iphdr_len + 8) {
251+
errf("nat: udp packet too short");
252+
return -1;
253+
}
254+
udp_hdr_t *udphdr = ip_payload;
255+
ADJUST_CHECKSUM(acc, udphdr->checksum);
248256
}
249-
udp_hdr_t *udphdr = ip_payload;
250-
ADJUST_CHECKSUM(acc, udphdr->checksum);
251257
}
252258
return 0;
253259
}

0 commit comments

Comments
 (0)