From 45f67c23fd2d1040def1364733cb0d38197833f7 Mon Sep 17 00:00:00 2001 From: Luis Neto Date: Thu, 30 Jan 2025 03:11:54 -0800 Subject: [PATCH] TUN-8858: update go to 1.22.10 and include quic-go FIPS changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary To have support for new curves and to achieve FIPS compliance Cloudflared must be released with [Go-Boring-1.22.10](https://bitbucket.cfdata.org/projects/PLAT/repos/goboring/browse?at=refs/heads/go-boring/1.22.10 "Follow link") along with the quic-go patches.  Closes TUN-8858 --- .teamcity/install-cloudflare-go.sh | 4 +- .teamcity/windows/install-cloudflare-go.ps1 | 4 +- Dockerfile | 2 +- Dockerfile.amd64 | 2 +- Dockerfile.arm64 | 2 +- build-packages-fips.sh | 2 +- cfsetup.yaml | 2 +- dev.Dockerfile | 4 +- go.mod | 3 ++ go.sum | 4 +- .../github.com/quic-go/quic-go/connection.go | 14 ++++- .../internal/handshake/cipher_suite.go | 18 +++++-- .../handshake/xor_nonce_aead_boring.go | 51 +++++++++++++++++++ .../handshake/xor_nonce_aead_noboring.go | 13 +++++ vendor/modules.txt | 3 +- 15 files changed, 108 insertions(+), 20 deletions(-) create mode 100644 vendor/github.com/quic-go/quic-go/internal/handshake/xor_nonce_aead_boring.go create mode 100644 vendor/github.com/quic-go/quic-go/internal/handshake/xor_nonce_aead_noboring.go diff --git a/.teamcity/install-cloudflare-go.sh b/.teamcity/install-cloudflare-go.sh index 9677ed7e..96d7056b 100755 --- a/.teamcity/install-cloudflare-go.sh +++ b/.teamcity/install-cloudflare-go.sh @@ -3,6 +3,6 @@ cd /tmp git clone -q https://github.com/cloudflare/go cd go/src -# https://github.com/cloudflare/go/tree/f4334cdc0c3f22a3bfdd7e66f387e3ffc65a5c38 is version go1.22.5-devel-cf -git checkout -q f4334cdc0c3f22a3bfdd7e66f387e3ffc65a5c38 +# https://github.com/cloudflare/go/tree/af19da5605ca11f85776ef7af3384a02a315a52b is version go1.22.5-devel-cf +git checkout -q af19da5605ca11f85776ef7af3384a02a315a52b ./make.bash diff --git a/.teamcity/windows/install-cloudflare-go.ps1 b/.teamcity/windows/install-cloudflare-go.ps1 index 6ff957b9..a7ed1e11 100644 --- a/.teamcity/windows/install-cloudflare-go.ps1 +++ b/.teamcity/windows/install-cloudflare-go.ps1 @@ -9,8 +9,8 @@ Set-Location "$Env:Temp" git clone -q https://github.com/cloudflare/go Write-Output "Building go..." cd go/src -# https://github.com/cloudflare/go/tree/f4334cdc0c3f22a3bfdd7e66f387e3ffc65a5c38 is version go1.22.5-devel-cf -git checkout -q f4334cdc0c3f22a3bfdd7e66f387e3ffc65a5c38 +# https://github.com/cloudflare/go/tree/af19da5605ca11f85776ef7af3384a02a315a52b is version go1.22.5-devel-cf +git checkout -q af19da5605ca11f85776ef7af3384a02a315a52b & ./make.bat Write-Output "Installed" diff --git a/Dockerfile b/Dockerfile index 66674c2a..72e4935e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ # use a builder image for building cloudflare ARG TARGET_GOOS ARG TARGET_GOARCH -FROM golang:1.22.5 as builder +FROM golang:1.22.10 as builder ENV GO111MODULE=on \ CGO_ENABLED=0 \ TARGET_GOOS=${TARGET_GOOS} \ diff --git a/Dockerfile.amd64 b/Dockerfile.amd64 index c375d801..952fc6f3 100644 --- a/Dockerfile.amd64 +++ b/Dockerfile.amd64 @@ -1,5 +1,5 @@ # use a builder image for building cloudflare -FROM golang:1.22.5 as builder +FROM golang:1.22.10 as builder ENV GO111MODULE=on \ CGO_ENABLED=0 \ # the CONTAINER_BUILD envvar is used set github.com/cloudflare/cloudflared/metrics.Runtime=virtual diff --git a/Dockerfile.arm64 b/Dockerfile.arm64 index b617d7ae..44f6e017 100644 --- a/Dockerfile.arm64 +++ b/Dockerfile.arm64 @@ -1,5 +1,5 @@ # use a builder image for building cloudflare -FROM golang:1.22.5 as builder +FROM golang:1.22.10 as builder ENV GO111MODULE=on \ CGO_ENABLED=0 \ # the CONTAINER_BUILD envvar is used set github.com/cloudflare/cloudflared/metrics.Runtime=virtual diff --git a/build-packages-fips.sh b/build-packages-fips.sh index 0ec3b3c9..e1b6e791 100755 --- a/build-packages-fips.sh +++ b/build-packages-fips.sh @@ -17,7 +17,7 @@ make cloudflared-deb mv cloudflared-fips\_$VERSION\_$arch.deb $ARTIFACT_DIR/cloudflared-fips-linux-$arch.deb # rpm packages invert the - and _ and use x86_64 instead of amd64. -RPMVERSION=$(echo $VERSION|sed -r 's/-/_/g') +RPMVERSION=$(echo $VERSION | sed -r 's/-/_/g') RPMARCH="x86_64" make cloudflared-rpm mv cloudflared-fips-$RPMVERSION-1.$RPMARCH.rpm $ARTIFACT_DIR/cloudflared-fips-linux-$RPMARCH.rpm diff --git a/cfsetup.yaml b/cfsetup.yaml index 7c7ac750..284eff67 100644 --- a/cfsetup.yaml +++ b/cfsetup.yaml @@ -1,4 +1,4 @@ -pinned_go: &pinned_go go-boring=1.22.5-1 +pinned_go: &pinned_go go-boring=1.22.10-1 build_dir: &build_dir /cfsetup_build default-flavor: bookworm diff --git a/dev.Dockerfile b/dev.Dockerfile index 8986040a..8d15784f 100644 --- a/dev.Dockerfile +++ b/dev.Dockerfile @@ -1,6 +1,6 @@ -FROM golang:1.22.5 as builder +FROM golang:1.22.10 as builder ENV GO111MODULE=on \ - CGO_ENABLED=0 + CGO_ENABLED=0 WORKDIR /go/src/github.com/cloudflare/cloudflared/ RUN apt-get update COPY . . diff --git a/go.mod b/go.mod index 11e8f0f5..ebafd54e 100644 --- a/go.mod +++ b/go.mod @@ -102,3 +102,6 @@ replace github.com/urfave/cli/v2 => github.com/ipostelnik/cli/v2 v2.3.1-0.202103 replace github.com/prometheus/golang_client => github.com/prometheus/golang_client v1.12.1 replace gopkg.in/yaml.v3 => gopkg.in/yaml.v3 v3.0.1 + +// This fork is based on quic-go v0.45 +replace github.com/quic-go/quic-go => github.com/chungthuang/quic-go v0.45.1-0.20250128102735-2687bd175910 diff --git a/go.sum b/go.sum index 1865726c..7afb8f40 100644 --- a/go.sum +++ b/go.sum @@ -7,6 +7,8 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chungthuang/quic-go v0.45.1-0.20250128102735-2687bd175910 h1:/hTvBpxBDj/3NIzTodi1oEOyNBpirvgDSPKSV7VqAZU= +github.com/chungthuang/quic-go v0.45.1-0.20250128102735-2687bd175910/go.mod h1:1dLehS7TIR64+vxGR70GDcatWTOtMX2PUtnKsjbTurI= github.com/coredns/caddy v1.1.1 h1:2eYKZT7i6yxIfGP3qLJoJ7HAsDJqYB+X68g4NYjSrE0= github.com/coredns/caddy v1.1.1/go.mod h1:A6ntJQlAWuQfFlsd9hvigKbo2WS0VUs2l1e2F+BawD4= github.com/coredns/coredns v1.11.3 h1:8RjnpZc42db5th84/QJKH2i137ecJdzZK1HJwhetSPk= @@ -173,8 +175,6 @@ github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+a github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= -github.com/quic-go/quic-go v0.45.0 h1:OHmkQGM37luZITyTSu6ff03HP/2IrwDX1ZFiNEhSFUE= -github.com/quic-go/quic-go v0.45.0/go.mod h1:1dLehS7TIR64+vxGR70GDcatWTOtMX2PUtnKsjbTurI= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= diff --git a/vendor/github.com/quic-go/quic-go/connection.go b/vendor/github.com/quic-go/quic-go/connection.go index d65f7c2e..0dbfa574 100644 --- a/vendor/github.com/quic-go/quic-go/connection.go +++ b/vendor/github.com/quic-go/quic-go/connection.go @@ -8,7 +8,9 @@ import ( "fmt" "io" "net" + "os" "reflect" + "strconv" "sync" "sync/atomic" "time" @@ -288,6 +290,16 @@ var newConnection = func( s.logger, ) s.maxPayloadSizeEstimate.Store(uint32(estimateMaxPayloadSize(protocol.ByteCount(s.config.InitialPacketSize)))) + // Allow server to define custom MaxUDPPayloadSize + maxUDPPayloadSize := protocol.MaxPacketBufferSize + if maxPacketSize := os.Getenv("TUNNEL_MAX_QUIC_PACKET_SIZE"); maxPacketSize != "" { + if customMaxPacketSize, err := strconv.ParseUint(maxPacketSize, 10, 64); err == nil { + maxUDPPayloadSize = int(customMaxPacketSize) + } else { + utils.DefaultLogger.Errorf("failed to parse TUNNEL_MAX_QUIC_PACKET_SIZE: %v", err) + } + } + params := &wire.TransportParameters{ InitialMaxStreamDataBidiLocal: protocol.ByteCount(s.config.InitialStreamReceiveWindow), InitialMaxStreamDataBidiRemote: protocol.ByteCount(s.config.InitialStreamReceiveWindow), @@ -298,7 +310,7 @@ var newConnection = func( MaxUniStreamNum: protocol.StreamNum(s.config.MaxIncomingUniStreams), MaxAckDelay: protocol.MaxAckDelayInclGranularity, AckDelayExponent: protocol.AckDelayExponent, - MaxUDPPayloadSize: protocol.MaxPacketBufferSize, + MaxUDPPayloadSize: protocol.ByteCount(maxUDPPayloadSize), DisableActiveMigration: true, StatelessResetToken: &statelessResetToken, OriginalDestinationConnectionID: origDestConnID, diff --git a/vendor/github.com/quic-go/quic-go/internal/handshake/cipher_suite.go b/vendor/github.com/quic-go/quic-go/internal/handshake/cipher_suite.go index d8a381da..fd3da738 100644 --- a/vendor/github.com/quic-go/quic-go/internal/handshake/cipher_suite.go +++ b/vendor/github.com/quic-go/quic-go/internal/handshake/cipher_suite.go @@ -12,7 +12,9 @@ import ( // These cipher suite implementations are copied from the standard library crypto/tls package. -const aeadNonceLength = 12 +const ( + aeadNonceLength = 12 +) type cipherSuite struct { ID uint16 @@ -44,12 +46,13 @@ func aeadAESGCMTLS13(key, nonceMask []byte) *xorNonceAEAD { if err != nil { panic(err) } - aead, err := cipher.NewGCM(aes) + + aead, err := newAEAD(aes) if err != nil { panic(err) } - ret := &xorNonceAEAD{aead: aead} + ret := &xorNonceAEAD{aead: aead, hasSeenNonceZero: false} copy(ret.nonceMask[:], nonceMask) return ret } @@ -71,8 +74,9 @@ func aeadChaCha20Poly1305(key, nonceMask []byte) *xorNonceAEAD { // xorNonceAEAD wraps an AEAD by XORing in a fixed pattern to the nonce // before each call. type xorNonceAEAD struct { - nonceMask [aeadNonceLength]byte - aead cipher.AEAD + nonceMask [aeadNonceLength]byte + aead cipher.AEAD + hasSeenNonceZero bool // This value denotes if the aead field was used with a nonce = 0 } func (f *xorNonceAEAD) NonceSize() int { return 8 } // 64-bit sequence number @@ -80,6 +84,10 @@ func (f *xorNonceAEAD) Overhead() int { return f.aead.Overhead() } func (f *xorNonceAEAD) explicitNonceLen() int { return 0 } func (f *xorNonceAEAD) Seal(out, nonce, plaintext, additionalData []byte) []byte { + return f.seal(nonce, out, plaintext, additionalData) +} + +func (f *xorNonceAEAD) doSeal(nonce, out, plaintext, additionalData []byte) []byte { for i, b := range nonce { f.nonceMask[4+i] ^= b } diff --git a/vendor/github.com/quic-go/quic-go/internal/handshake/xor_nonce_aead_boring.go b/vendor/github.com/quic-go/quic-go/internal/handshake/xor_nonce_aead_boring.go new file mode 100644 index 00000000..cc44c1ac --- /dev/null +++ b/vendor/github.com/quic-go/quic-go/internal/handshake/xor_nonce_aead_boring.go @@ -0,0 +1,51 @@ +//go:build boringcrypto + +package handshake + +import ( + "crypto/cipher" + "crypto/tls" + "os" + "strings" +) + +var goBoringDisabled bool = strings.TrimSpace(os.Getenv("QUIC_GO_DISABLE_BORING")) == "1" + +func newAEAD(aes cipher.Block) (cipher.AEAD, error) { + if goBoringDisabled { + // In case Go Boring is disabled then + // fallback to normal cryptographic procedure. + return cipher.NewGCM(aes) + } + return tls.NewGCMTLS13(aes) +} + +func allZeros(nonce []byte) bool { + for _, e := range nonce { + if e != 0 { + return false + } + } + return true +} + +func (f *xorNonceAEAD) sealZeroNonce() { + f.doSeal([]byte{}, []byte{}, []byte{}, []byte{}) +} + +func (f *xorNonceAEAD) seal(nonce, out, plaintext, additionalData []byte) []byte { + if !goBoringDisabled { + if !f.hasSeenNonceZero { + // BoringSSL expects that the first nonce passed to the + // AEAD instance is zero. + // At this point the nonce argument is either zero or + // an artificial one will be passed to the AEAD through + // [sealZeroNonce] + f.hasSeenNonceZero = true + if !allZeros(nonce) { + f.sealZeroNonce() + } + } + } + return f.doSeal(nonce, out, plaintext, additionalData) +} diff --git a/vendor/github.com/quic-go/quic-go/internal/handshake/xor_nonce_aead_noboring.go b/vendor/github.com/quic-go/quic-go/internal/handshake/xor_nonce_aead_noboring.go new file mode 100644 index 00000000..147269b5 --- /dev/null +++ b/vendor/github.com/quic-go/quic-go/internal/handshake/xor_nonce_aead_noboring.go @@ -0,0 +1,13 @@ +//go:build !boringcrypto + +package handshake + +import "crypto/cipher" + +func newAEAD(aes cipher.Block) (cipher.AEAD, error) { + return cipher.NewGCM(aes) +} + +func (f *xorNonceAEAD) seal(nonce, out, plaintext, additionalData []byte) []byte { + return f.doSeal(nonce, out, plaintext, additionalData) +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 468e4361..6e282412 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -221,7 +221,7 @@ github.com/prometheus/common/model github.com/prometheus/procfs github.com/prometheus/procfs/internal/fs github.com/prometheus/procfs/internal/util -# github.com/quic-go/quic-go v0.45.0 +# github.com/quic-go/quic-go v0.45.0 => github.com/chungthuang/quic-go v0.45.1-0.20250128102735-2687bd175910 ## explicit; go 1.21 github.com/quic-go/quic-go github.com/quic-go/quic-go/internal/ackhandler @@ -557,3 +557,4 @@ zombiezen.com/go/capnproto2/std/capnp/rpc # github.com/urfave/cli/v2 => github.com/ipostelnik/cli/v2 v2.3.1-0.20210324024421-b6ea8234fe3d # github.com/prometheus/golang_client => github.com/prometheus/golang_client v1.12.1 # gopkg.in/yaml.v3 => gopkg.in/yaml.v3 v3.0.1 +# github.com/quic-go/quic-go => github.com/chungthuang/quic-go v0.45.1-0.20250128102735-2687bd175910