@@ -171,21 +171,24 @@ int nat_fix_upstream(nat_ctx_t *ctx, unsigned char *buf, size_t buflen,
171
171
acc = client -> input_tun_ip - iphdr -> saddr ;
172
172
ADJUST_CHECKSUM (acc , iphdr -> checksum );
173
173
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 );
179
191
}
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 );
189
192
}
190
193
return 0 ;
191
194
}
@@ -233,21 +236,24 @@ int nat_fix_downstream(nat_ctx_t *ctx, unsigned char *buf, size_t buflen,
233
236
234
237
ADJUST_CHECKSUM (acc , iphdr -> checksum );
235
238
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 );
248
256
}
249
- udp_hdr_t * udphdr = ip_payload ;
250
- ADJUST_CHECKSUM (acc , udphdr -> checksum );
251
257
}
252
258
return 0 ;
253
259
}
0 commit comments