mirror of
https://github.com/qdm12/gluetun.git
synced 2026-05-07 04:20:12 +02:00
be92aa2ac4
- Existing option `WIREGUARD_MTU` , if set, disables PMTUD and is used - New option `PMTUD_ICMP_ADDRESSES=1.1.1.1,8.8.8.8` and `PMTUD_TCP_ADDRESSES=1.1.1.1:443,8.8.8.8:443` - ICMP PMTUD now targets external-by-default IP addresses - New TCP PMTUD (binary search only) as a second MTU confirmation and fallback mechanism. - Force set TCP MSS to MTU - IP header - TCP base header - "magic 20 bytes" 🎆 - Fix #3108
74 lines
2.3 KiB
Go
74 lines
2.3 KiB
Go
package ip
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"net/netip"
|
|
"syscall"
|
|
|
|
"github.com/qdm12/gluetun/internal/pmtud/constants"
|
|
)
|
|
|
|
func HeaderV4(srcIP, dstIP netip.Addr, payloadLength uint32) []byte {
|
|
ipHeader := make([]byte, constants.IPv4HeaderLength)
|
|
const version byte = 4
|
|
const headerLength byte = 20 / 4 // in 32-bit words
|
|
ipHeader[0] = (version << 4) | headerLength //nolint:mnd
|
|
ipHeader[1] = 0 // type of Service
|
|
putUint16(ipHeader[2:], uint16(constants.IPv4HeaderLength+payloadLength)) //nolint:gosec
|
|
ipHeader[4], ipHeader[5] = 0, 0 // identification
|
|
const flagsAndOffset uint16 = 0x4000 // DF bit set
|
|
putUint16(ipHeader[6:], flagsAndOffset)
|
|
ipHeader[8] = 64 // ttl
|
|
ipHeader[9] = syscall.IPPROTO_TCP
|
|
srcIPBytes := srcIP.As4()
|
|
copy(ipHeader[12:16], srcIPBytes[:])
|
|
dstIPBytes := dstIP.As4()
|
|
copy(ipHeader[16:20], dstIPBytes[:])
|
|
|
|
checksum := ipChecksum(ipHeader)
|
|
ipHeader[10] = byte(checksum >> 8) //nolint:mnd
|
|
ipHeader[11] = byte(checksum & 0xff) //nolint:mnd
|
|
|
|
return ipHeader
|
|
}
|
|
|
|
// ipChecksum calculates the checksum for the IP header.
|
|
//
|
|
//nolint:mnd
|
|
func ipChecksum(header []byte) uint16 {
|
|
sum := uint32(0)
|
|
for i := 0; i < len(header)-1; i += 2 {
|
|
sum += uint32(header[i])<<8 + uint32(header[i+1])
|
|
}
|
|
if len(header)%2 != 0 {
|
|
sum += uint32(header[len(header)-1]) << 8
|
|
}
|
|
for (sum >> 16) > 0 {
|
|
sum = (sum & 0xFFFF) + (sum >> 16)
|
|
}
|
|
return ^uint16(sum) //nolint:gosec
|
|
}
|
|
|
|
// HeaderV6 makes an IPv6 header.
|
|
// payloadLen is the length of the payload following the header.
|
|
// nextHeader can be byte([syscall.IPPROTO_TCP]) for example.
|
|
func HeaderV6(srcIP, dstIP netip.Addr,
|
|
payloadLen uint16, nextHeader byte,
|
|
) []byte {
|
|
ipv6Header := make([]byte, constants.IPv6HeaderLength)
|
|
ipv6Header[0] = 0x60 // version (4 bits) | traffic Class (4 bits)
|
|
ipv6Header[1] = 0x00 // traffic Class (4 bits) | flow label (4 bits)
|
|
|
|
// Flow Label (remaining 16 bits)
|
|
ipv6Header[2] = 0x00
|
|
ipv6Header[3] = 0x00
|
|
|
|
binary.BigEndian.PutUint16(ipv6Header[4:], payloadLen)
|
|
ipv6Header[6] = nextHeader
|
|
const hopLimit = 64
|
|
ipv6Header[7] = hopLimit
|
|
copy(ipv6Header[8:24], srcIP.AsSlice())
|
|
copy(ipv6Header[24:40], dstIP.AsSlice())
|
|
return ipv6Header
|
|
}
|