mirror of
https://github.com/cloudflare/cloudflared.git
synced 2026-06-22 20:00:16 +00:00
f674b82e2a
Introduce a new crypto/ package as the single source of truth for TLS curve preferences used on every edge-facing connection, and adopt X25519MLKEM768 as the primary post-quantum key exchange for both QUIC and HTTP/2: PQ Prefer (default): X25519MLKEM768, P256Kyber768Draft00, CurveP256 PQ Strict (--post-quantum): X25519MLKEM768, P256Kyber768Draft00 The curve list is identical under FIPS and non-FIPS builds, so crypto.GetCurvePreferences takes only a features.PostQuantumMode and returns a fresh slice on every call. HTTP/2 now applies these curve preferences the same way QUIC does. The previous PostQuantumStrict rejection in serveHTTP2 and the forced QUIC-only selection in NewProtocolSelector are removed since both transports support the same post-quantum curves; the needPQ parameter is dropped from NewProtocolSelector accordingly. Also fix a shared tls.Config race: both the QUIC and HTTP/2 paths now Clone() the per-protocol entry from TunnelConfig.EdgeTLSConfigs before mutating CurvePreferences instead of writing through the shared map entry. Legacy Kyber draft curve X25519Kyber768Draft00 and the unused removeDuplicates helper are removed along with the old supervisor/pqtunnels.go / _test.go files. AGENTS.md is updated with guidance on the new crypto/ package, the cfdcrypto import alias, the tls.Config cloning rule, and the lint workflow implications of .golangci.yaml's whole-files: true setting.
9.2 KiB
9.2 KiB
Cloudflared
Cloudflare's command-line tool and networking daemon written in Go. Production-grade tunneling and network connectivity services used by millions of developers and organizations worldwide.
Essential Commands
Build & Test (Always run before commits)
# Full development check (run before any commit)
make test lint
# Build for current platform
make cloudflared
# Run all unit tests with coverage
make test
make cover
# Run specific test
go test -run TestFunctionName ./path/to/package
# Run tests with race detection
go test -race ./...
Platform-Specific Builds
# Linux
TARGET_OS=linux TARGET_ARCH=amd64 make cloudflared
# Windows
TARGET_OS=windows TARGET_ARCH=amd64 make cloudflared
# macOS ARM64
TARGET_OS=darwin TARGET_ARCH=arm64 make cloudflared
# FIPS compliant build
FIPS=true make cloudflared
Code Quality & Formatting
# Run linter (38+ enabled linters)
make lint
# Auto-fix formatting
make fmt
gofmt -w .
goimports -w .
# Security scanning
make vet
# Component tests (Python integration tests)
cd component-tests && python -m pytest test_file.py::test_function_name
Notes on linting:
.golangci.yamlis configured withnew-from-revandwhole-files: true. Touching a file triggers linting of the ENTIRE file, not just the changed hunks. Expect to fix pre-existing issues in files you modify, or add targeted// nolint: <linter>comments with a short justification.- Prefer
defer func() { _ = resource.Close() }()overdefer resource.Close()forio.Closervalues whose error truly does not matter — this satisfieserrcheckwithout hiding real failures elsewhere.
Project Knowledge
Package Structure
- Use meaningful package names that reflect functionality
- Package names should be lowercase, single words when possible
- Avoid generic names like
util,common,helper
Well-known shared packages
crypto/: Single source of truth for TLS curve preferences and other cryptographic primitives shared by every edge-facing transport. Import ascfdcrypto "github.com/cloudflare/cloudflared/crypto"to avoid colliding with the standard library'scryptopackage. Do NOT duplicate TLS curve or cipher selection logic in other packages.tlsconfig/: Builds the base*tls.Configused for edge connections (CreateTunnelConfig) and loads origin/CA pools. Curve selection is intentionally NOT set here; it is applied per-connection from thecrypto/package so the same config can be cloned and reused across protocols.features/: Runtime feature flags includingPostQuantumMode(PostQuantumPrefer= default,PostQuantumStrict=--post-quantum).fips/: Build-tag driven FIPS detection. Onlyfips.IsFipsEnabled()is exposed; never branch onfipsEnabledinside a function if the two branches return the same value.
Function and Method Guidelines
// Good: Clear purpose, proper error handling
func (c *Connection) HandleRequest(ctx context.Context, req *http.Request) error {
if req == nil {
return errors.New("request cannot be nil")
}
// Implementation...
return nil
}
Error Handling
- Always handle errors explicitly, never ignore them
- Use
fmt.Errorffor error wrapping - Create meaningful error messages with context
- Use error variables for common errors
// Good error handling patterns
if err != nil {
return fmt.Errorf("failed to process connection: %w", err)
}
Logging Standards
- Use
github.com/rs/zerologfor structured logging - Include relevant context fields
- Use appropriate log levels (Debug, Info, Warn, Error)
logger.Info().
Str("tunnelID", tunnel.ID).
Int("connIndex", connIndex).
Msg("Connection established")
Testing Patterns
- Use
github.com/stretchr/testifyfor assertions - Test files end with
_test.go - Use table-driven tests for multiple scenarios
- Always use
t.Parallel()for parallel-safe tests - Use meaningful test names that describe behavior
func TestMetricsListenerCreation(t *testing.T) {
t.Parallel()
// Test implementation
assert.Equal(t, expected, actual)
require.NoError(t, err)
}
Constants and Variables
const (
MaxGracePeriod = time.Minute * 3
MaxConcurrentStreams = math.MaxUint32
LogFieldConnIndex = "connIndex"
)
var (
// Group related variables
switchingProtocolText = fmt.Sprintf("%d %s", http.StatusSwitchingProtocols, http.StatusText(http.StatusSwitchingProtocols))
flushableContentTypes = []string{sseContentType, grpcContentType, sseJsonContentType}
)
Type Definitions
- Define interfaces close to their usage
- Keep interfaces small and focused
- Use descriptive names for complex types
type TunnelConnection interface {
Serve(ctx context.Context) error
}
type TunnelProperties struct {
Credentials Credentials
QuickTunnelUrl string
}
Key Architectural Patterns
Context Usage
- Always accept
context.Contextas first parameter for long-running operations - Respect context cancellation in loops and blocking operations
- Pass context through call chains
Concurrency
- Use channels for goroutine communication
- Protect shared state with mutexes
- Prefer
sync.RWMutexfor read-heavy workloads *tls.Configvalues stored in shared maps (e.g.TunnelConfig.EdgeTLSConfigs) must beClone()d before mutating per-connection fields likeCurvePreferencesorNextProtos. Writing through the shared pointer races with concurrent connection attempts.
TLS & Post-Quantum key exchange
- Per-connection TLS configuration for edge connections is built via
cfdcrypto.TLSConfigWithCurvePreferences(tlsConfig, pqMode). It clones the provided*tls.Configand setsCurvePreferencesbased onpqMode, so callers never need to clone or mutateCurvePreferencesthemselves. Do NOT reach for the package-privategetCurvePreferenceshelper; the exportedTLSConfigWithCurvePreferencesis the only supported entry point. - Two PQ modes are supported and apply identically to QUIC and HTTP/2:
PostQuantumPrefer(default):[X25519MLKEM768, P256Kyber768Draft00, CurveP256]PostQuantumStrict(--post-quantum):[X25519MLKEM768, P256Kyber768Draft00]
- FIPS and non-FIPS builds use the same curve list. Do NOT reintroduce a
fipsEnabledbranch in curve-selection code; if the two modes ever diverge, express the divergence insidecrypto/so call sites remain untouched. - HTTP/2 supports post-quantum handshakes. Never re-add a
PostQuantumStrict-based rejection to H2 code paths, and never force--post-quantumto select QUIC-only in protocol selection.
Configuration
- Use structured configuration with validation
- Support both file-based and CLI flag configuration
- Provide sensible defaults
Metrics and Observability
- Instrument code with Prometheus metrics
- Use OpenTelemetry for distributed tracing
- Include structured logging with relevant context
Boundaries
✅ Always Do
- Run
make test lintbefore any commit - Handle all errors explicitly with proper context
- Use
github.com/rs/zerologfor all logging - Add
t.Parallel()to all parallel-safe tests - Follow the import grouping conventions
- Use meaningful variable and function names
- Include context.Context for long-running operations
- Close resources in defer statements
⚠️ Ask First Before
- Adding new dependencies to go.mod
- Modifying CI/CD configuration files
- Changing build system or Makefile
- Modifying component test infrastructure
- Adding new linter rules or changing golangci-lint config
- Making breaking changes to public APIs
- Changing logging levels or structured logging fields
🚫 Never Do
- Ignore errors without explicit handling (
_ = err) - Use generic package names (
util,helper,common) - Commit code that fails
make test lint - Use
fmt.Print*instead of structured logging - Modify vendor dependencies directly
- Commit secrets, credentials, or sensitive data
- Use deprecated or unsafe Go patterns
- Skip testing for new functionality
- Remove existing tests unless they're genuinely invalid
Dependencies Management
- Use Go modules (
go.mod) exclusively - Vendor dependencies for reproducible builds
- Keep dependencies up-to-date and secure
- Prefer standard library when possible
- Cloudflared uses a fork of quic-go always check release notes before bumping this dependency.
Security Considerations
- FIPS compliance support available
- Vulnerability scanning integrated in CI
- Credential handling follows security best practices
- Network security with TLS/QUIC protocols
- Regular security audits and updates
- Post quantum encryption
Common Patterns to Follow
- Graceful shutdown: Always implement proper cleanup
- Resource management: Close resources in defer statements
- Error propagation: Wrap errors with meaningful context
- Configuration validation: Validate inputs early
- Logging consistency: Use structured logging throughout
- Testing coverage: Aim for comprehensive test coverage
- Documentation: Comment exported functions and types
Remember: This is a mission-critical networking tool used in production by many organizations. Code quality, security, and reliability are paramount.