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
84 lines
2.4 KiB
Go
84 lines
2.4 KiB
Go
package icmp
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"golang.org/x/net/icmp"
|
|
)
|
|
|
|
var (
|
|
ErrNextHopMTUTooLow = errors.New("ICMP Next Hop MTU is too low")
|
|
ErrNextHopMTUTooHigh = errors.New("ICMP Next Hop MTU is too high")
|
|
)
|
|
|
|
func checkMTU(mtu, minMTU, physicalLinkMTU uint32) (err error) {
|
|
switch {
|
|
case mtu < minMTU:
|
|
return fmt.Errorf("%w: %d", ErrNextHopMTUTooLow, mtu)
|
|
case mtu > physicalLinkMTU:
|
|
return fmt.Errorf("%w: %d is larger than physical link MTU %d",
|
|
ErrNextHopMTUTooHigh, mtu, physicalLinkMTU)
|
|
default:
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func checkInvokingReplyIDMatch(icmpProtocol int, received []byte,
|
|
outboundMessage *icmp.Message,
|
|
) (match bool, err error) {
|
|
inboundMessage, err := icmp.ParseMessage(icmpProtocol, received)
|
|
if err != nil {
|
|
return false, fmt.Errorf("parsing invoking packet: %w", err)
|
|
}
|
|
inboundBody, ok := inboundMessage.Body.(*icmp.Echo)
|
|
if !ok {
|
|
return false, fmt.Errorf("%w: %T", ErrBodyUnsupported, inboundMessage.Body)
|
|
}
|
|
outboundBody := outboundMessage.Body.(*icmp.Echo) //nolint:forcetypeassert
|
|
return inboundBody.ID == outboundBody.ID, nil
|
|
}
|
|
|
|
var ErrIDMismatch = errors.New("ICMP id mismatch")
|
|
|
|
func checkEchoReply(icmpProtocol int, received []byte,
|
|
outboundMessage *icmp.Message, truncatedBody bool,
|
|
) (err error) {
|
|
inboundMessage, err := icmp.ParseMessage(icmpProtocol, received)
|
|
if err != nil {
|
|
return fmt.Errorf("parsing invoking packet: %w", err)
|
|
}
|
|
inboundBody, ok := inboundMessage.Body.(*icmp.Echo)
|
|
if !ok {
|
|
return fmt.Errorf("%w: %T", ErrBodyUnsupported, inboundMessage.Body)
|
|
}
|
|
outboundBody := outboundMessage.Body.(*icmp.Echo) //nolint:forcetypeassert
|
|
if inboundBody.ID != outboundBody.ID {
|
|
return fmt.Errorf("%w: sent id %d and received id %d",
|
|
ErrIDMismatch, outboundBody.ID, inboundBody.ID)
|
|
}
|
|
err = checkEchoBodies(outboundBody.Data, inboundBody.Data, truncatedBody)
|
|
if err != nil {
|
|
return fmt.Errorf("checking sent and received bodies: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
var ErrEchoDataMismatch = errors.New("ICMP data mismatch")
|
|
|
|
func checkEchoBodies(sent, received []byte, receivedTruncated bool) (err error) {
|
|
if len(received) > len(sent) {
|
|
return fmt.Errorf("%w: sent %d bytes and received %d bytes",
|
|
ErrEchoDataMismatch, len(sent), len(received))
|
|
}
|
|
if receivedTruncated {
|
|
sent = sent[:len(received)]
|
|
}
|
|
if !bytes.Equal(received, sent) {
|
|
return fmt.Errorf("%w: sent %x and received %x",
|
|
ErrEchoDataMismatch, sent, received)
|
|
}
|
|
return nil
|
|
}
|