TUN-6339: Add config for IPv6 support
This commit is contained in:
parent
d714a62bd3
commit
ee80e55833
|
@ -514,6 +514,12 @@ func tunnelFlags(shouldHide bool) []cli.Flag {
|
||||||
Usage: "Cloudflare Edge region to connect to. Omit or set to empty to connect to the global region.",
|
Usage: "Cloudflare Edge region to connect to. Omit or set to empty to connect to the global region.",
|
||||||
EnvVars: []string{"TUNNEL_REGION"},
|
EnvVars: []string{"TUNNEL_REGION"},
|
||||||
}),
|
}),
|
||||||
|
altsrc.NewStringFlag(&cli.StringFlag{
|
||||||
|
Name: "edge-ip-version",
|
||||||
|
Usage: "Cloudflare Edge ip address version to connect with. {4, 6, auto}",
|
||||||
|
EnvVars: []string{"TUNNEL_EDGE_IP_VERSION"},
|
||||||
|
Hidden: true,
|
||||||
|
}),
|
||||||
altsrc.NewStringFlag(&cli.StringFlag{
|
altsrc.NewStringFlag(&cli.StringFlag{
|
||||||
Name: tlsconfig.CaCertFlag,
|
Name: tlsconfig.CaCertFlag,
|
||||||
Usage: "Certificate Authority authenticating connections with Cloudflare's edge network.",
|
Usage: "Certificate Authority authenticating connections with Cloudflare's edge network.",
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
"golang.org/x/crypto/ssh/terminal"
|
"golang.org/x/crypto/ssh/terminal"
|
||||||
|
|
||||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/cliutil"
|
"github.com/cloudflare/cloudflared/cmd/cloudflared/cliutil"
|
||||||
|
"github.com/cloudflare/cloudflared/edgediscovery/allregions"
|
||||||
|
|
||||||
"github.com/cloudflare/cloudflared/config"
|
"github.com/cloudflare/cloudflared/config"
|
||||||
"github.com/cloudflare/cloudflared/connection"
|
"github.com/cloudflare/cloudflared/connection"
|
||||||
|
@ -324,6 +325,10 @@ func prepareTunnelConfig(
|
||||||
CompressionSetting: h2mux.CompressionSetting(uint64(c.Int("compression-quality"))),
|
CompressionSetting: h2mux.CompressionSetting(uint64(c.Int("compression-quality"))),
|
||||||
MetricsUpdateFreq: c.Duration("metrics-update-freq"),
|
MetricsUpdateFreq: c.Duration("metrics-update-freq"),
|
||||||
}
|
}
|
||||||
|
edgeIPVersion, err := parseConfigIPVersion(c.String("edge-ip-version"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
tunnelConfig := &supervisor.TunnelConfig{
|
tunnelConfig := &supervisor.TunnelConfig{
|
||||||
GracePeriod: gracePeriod,
|
GracePeriod: gracePeriod,
|
||||||
|
@ -332,6 +337,7 @@ func prepareTunnelConfig(
|
||||||
ClientID: clientID,
|
ClientID: clientID,
|
||||||
EdgeAddrs: c.StringSlice("edge"),
|
EdgeAddrs: c.StringSlice("edge"),
|
||||||
Region: c.String("region"),
|
Region: c.String("region"),
|
||||||
|
EdgeIPVersion: edgeIPVersion,
|
||||||
HAConnections: c.Int("ha-connections"),
|
HAConnections: c.Int("ha-connections"),
|
||||||
IncidentLookup: supervisor.NewIncidentLookup(),
|
IncidentLookup: supervisor.NewIncidentLookup(),
|
||||||
IsAutoupdated: c.Bool("is-autoupdated"),
|
IsAutoupdated: c.Bool("is-autoupdated"),
|
||||||
|
@ -404,3 +410,18 @@ func dedup(slice []string) []string {
|
||||||
}
|
}
|
||||||
return keys
|
return keys
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseConfigIPVersion returns the IP version from possible expected values from config
|
||||||
|
func parseConfigIPVersion(version string) (v allregions.ConfigIPVersion, err error) {
|
||||||
|
switch version {
|
||||||
|
case "4":
|
||||||
|
v = allregions.IPv4Only
|
||||||
|
case "6":
|
||||||
|
v = allregions.IPv6Only
|
||||||
|
case "auto":
|
||||||
|
v = allregions.Auto
|
||||||
|
default: // unspecified or invalid
|
||||||
|
err = fmt.Errorf("invalid value for edge-ip-version: %s", version)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
|
@ -18,6 +18,15 @@ func (e DupConnRegisterTunnelError) Error() string {
|
||||||
return "already connected to this server, trying another address"
|
return "already connected to this server, trying another address"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dial to edge server with quic failed
|
||||||
|
type EdgeQuicDialError struct {
|
||||||
|
Cause error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e EdgeQuicDialError) Error() string {
|
||||||
|
return "failed to dial to edge with quic: " + e.Cause.Error()
|
||||||
|
}
|
||||||
|
|
||||||
// RegisterTunnel error from server
|
// RegisterTunnel error from server
|
||||||
type ServerRegisterTunnelError struct {
|
type ServerRegisterTunnelError struct {
|
||||||
Cause error
|
Cause error
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package connection
|
package connection
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
|
@ -8,6 +9,7 @@ import (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
LogFieldLocation = "location"
|
LogFieldLocation = "location"
|
||||||
|
LogFieldIPAddress = "ip"
|
||||||
observerChannelBufferSize = 16
|
observerChannelBufferSize = 16
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -41,11 +43,12 @@ func (o *Observer) RegisterSink(sink EventSink) {
|
||||||
o.addSinkChan <- sink
|
o.addSinkChan <- sink
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Observer) logServerInfo(connIndex uint8, location, msg string) {
|
func (o *Observer) logServerInfo(connIndex uint8, location string, address net.IP, msg string) {
|
||||||
o.sendEvent(Event{Index: connIndex, EventType: Connected, Location: location})
|
o.sendEvent(Event{Index: connIndex, EventType: Connected, Location: location})
|
||||||
o.log.Info().
|
o.log.Info().
|
||||||
Uint8(LogFieldConnIndex, connIndex).
|
Uint8(LogFieldConnIndex, connIndex).
|
||||||
Str(LogFieldLocation, location).
|
Str(LogFieldLocation, location).
|
||||||
|
IPAddr(LogFieldIPAddress, address).
|
||||||
Msg(msg)
|
Msg(msg)
|
||||||
o.metrics.registerServerLocation(uint8ToString(connIndex), location)
|
o.metrics.registerServerLocation(uint8ToString(connIndex), location)
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@ func NewQUICConnection(
|
||||||
) (*QUICConnection, error) {
|
) (*QUICConnection, error) {
|
||||||
session, err := quic.DialAddr(edgeAddr.String(), tlsConfig, quicConfig)
|
session, err := quic.DialAddr(edgeAddr.String(), tlsConfig, quicConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to dial to edge: %w", err)
|
return nil, EdgeQuicDialError{Cause: err}
|
||||||
}
|
}
|
||||||
|
|
||||||
datagramMuxer, err := quicpogs.NewDatagramMuxer(session, logger)
|
datagramMuxer, err := quicpogs.NewDatagramMuxer(session, logger)
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"net"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
|
@ -114,7 +115,7 @@ func (rsc *registrationServerClient) RegisterConnection(
|
||||||
|
|
||||||
observer.metrics.regSuccess.WithLabelValues("registerConnection").Inc()
|
observer.metrics.regSuccess.WithLabelValues("registerConnection").Inc()
|
||||||
|
|
||||||
observer.logServerInfo(connIndex, conn.Location, fmt.Sprintf("Connection %s registered", conn.UUID))
|
observer.logServerInfo(connIndex, conn.Location, options.OriginLocalIP, fmt.Sprintf("Connection %s registered", conn.UUID))
|
||||||
observer.sendConnectedEvent(connIndex, conn.Location)
|
observer.sendConnectedEvent(connIndex, conn.Location)
|
||||||
|
|
||||||
return conn, nil
|
return conn, nil
|
||||||
|
@ -274,7 +275,7 @@ func (h *h2muxConnection) logServerInfo(ctx context.Context, rpcClient *tunnelSe
|
||||||
h.observer.log.Err(err).Msg("Failed to retrieve server information")
|
h.observer.log.Err(err).Msg("Failed to retrieve server information")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
h.observer.logServerInfo(h.connIndex, serverInfo.LocationName, "Connection established")
|
h.observer.logServerInfo(h.connIndex, serverInfo.LocationName, net.IP{}, "Connection established")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,10 +32,40 @@ var (
|
||||||
netLookupIP = net.LookupIP
|
netLookupIP = net.LookupIP
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ConfigIPVersion is the selection of IP versions from config
|
||||||
|
type ConfigIPVersion int8
|
||||||
|
|
||||||
|
const (
|
||||||
|
Auto ConfigIPVersion = 2
|
||||||
|
IPv4Only ConfigIPVersion = 4
|
||||||
|
IPv6Only ConfigIPVersion = 6
|
||||||
|
)
|
||||||
|
|
||||||
|
// IPVersion is the IP version of an EdgeAddr
|
||||||
|
type EdgeIPVersion int8
|
||||||
|
|
||||||
|
const (
|
||||||
|
V4 EdgeIPVersion = 4
|
||||||
|
V6 EdgeIPVersion = 6
|
||||||
|
)
|
||||||
|
|
||||||
|
// String returns the enum's constant name.
|
||||||
|
func (c EdgeIPVersion) String() string {
|
||||||
|
switch c {
|
||||||
|
case V4:
|
||||||
|
return "4"
|
||||||
|
case V6:
|
||||||
|
return "6"
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// EdgeAddr is a representation of possible ways to refer an edge location.
|
// EdgeAddr is a representation of possible ways to refer an edge location.
|
||||||
type EdgeAddr struct {
|
type EdgeAddr struct {
|
||||||
TCP *net.TCPAddr
|
TCP *net.TCPAddr
|
||||||
UDP *net.UDPAddr
|
UDP *net.UDPAddr
|
||||||
|
IPVersion EdgeIPVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the call to net.LookupSRV fails, try to fall back to DoT from Cloudflare directly.
|
// If the call to net.LookupSRV fails, try to fall back to DoT from Cloudflare directly.
|
||||||
|
@ -120,9 +150,14 @@ func resolveSRV(srv *net.SRV) ([]*EdgeAddr, error) {
|
||||||
}
|
}
|
||||||
addrs := make([]*EdgeAddr, len(ips))
|
addrs := make([]*EdgeAddr, len(ips))
|
||||||
for i, ip := range ips {
|
for i, ip := range ips {
|
||||||
|
version := V6
|
||||||
|
if ip.To4() != nil {
|
||||||
|
version = V4
|
||||||
|
}
|
||||||
addrs[i] = &EdgeAddr{
|
addrs[i] = &EdgeAddr{
|
||||||
TCP: &net.TCPAddr{IP: ip, Port: int(srv.Port)},
|
TCP: &net.TCPAddr{IP: ip, Port: int(srv.Port)},
|
||||||
UDP: &net.UDPAddr{IP: ip, Port: int(srv.Port)},
|
UDP: &net.UDPAddr{IP: ip, Port: int(srv.Port)},
|
||||||
|
IPVersion: version,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return addrs, nil
|
return addrs, nil
|
||||||
|
@ -143,9 +178,14 @@ func ResolveAddrs(addrs []string, log *zerolog.Logger) (resolved []*EdgeAddr) {
|
||||||
log.Error().Str(logFieldAddress, addr).Err(err).Msg("failed to resolve to UDP address")
|
log.Error().Str(logFieldAddress, addr).Err(err).Msg("failed to resolve to UDP address")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
version := V6
|
||||||
|
if udpAddr.IP.To4() != nil {
|
||||||
|
version = V4
|
||||||
|
}
|
||||||
resolved = append(resolved, &EdgeAddr{
|
resolved = append(resolved, &EdgeAddr{
|
||||||
TCP: tcpAddr,
|
TCP: tcpAddr,
|
||||||
UDP: udpAddr,
|
UDP: udpAddr,
|
||||||
|
IPVersion: version,
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ func newMockAddrs(port uint16, numRegions uint8, numAddrsPerRegion uint8) mockAd
|
||||||
IP: net.ParseIP(fmt.Sprintf("10.0.%v.%v", r, a)),
|
IP: net.ParseIP(fmt.Sprintf("10.0.%v.%v", r, a)),
|
||||||
Port: int(port),
|
Port: int(port),
|
||||||
}
|
}
|
||||||
addrs = append(addrs, &EdgeAddr{tcpAddr, udpAddr})
|
addrs = append(addrs, &EdgeAddr{tcpAddr, udpAddr, V4})
|
||||||
}
|
}
|
||||||
addrMap[srv] = addrs
|
addrMap[srv] = addrs
|
||||||
numAddrs += len(addrs)
|
numAddrs += len(addrs)
|
||||||
|
|
|
@ -63,7 +63,6 @@ var errEarlyShutdown = errors.New("shutdown started")
|
||||||
|
|
||||||
type tunnelError struct {
|
type tunnelError struct {
|
||||||
index int
|
index int
|
||||||
addr *allregions.EdgeAddr
|
|
||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,7 +234,7 @@ func (s *Supervisor) startFirstTunnel(
|
||||||
)
|
)
|
||||||
const firstConnIndex = 0
|
const firstConnIndex = 0
|
||||||
defer func() {
|
defer func() {
|
||||||
s.tunnelErrors <- tunnelError{index: firstConnIndex, addr: addr, err: err}
|
s.tunnelErrors <- tunnelError{index: firstConnIndex, err: err}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
addr, err = s.edgeIPs.GetAddr(firstConnIndex)
|
addr, err = s.edgeIPs.GetAddr(firstConnIndex)
|
||||||
|
@ -306,7 +305,7 @@ func (s *Supervisor) startTunnel(
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
defer func() {
|
defer func() {
|
||||||
s.tunnelErrors <- tunnelError{index: index, addr: addr, err: err}
|
s.tunnelErrors <- tunnelError{index: index, err: err}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
addr, err = s.edgeIPs.GetDifferentAddr(index)
|
addr, err = s.edgeIPs.GetDifferentAddr(index)
|
||||||
|
|
|
@ -43,6 +43,7 @@ type TunnelConfig struct {
|
||||||
CloseConnOnce *sync.Once // Used to close connectedSignal no more than once
|
CloseConnOnce *sync.Once // Used to close connectedSignal no more than once
|
||||||
EdgeAddrs []string
|
EdgeAddrs []string
|
||||||
Region string
|
Region string
|
||||||
|
EdgeIPVersion allregions.ConfigIPVersion
|
||||||
HAConnections int
|
HAConnections int
|
||||||
IncidentLookup IncidentLookup
|
IncidentLookup IncidentLookup
|
||||||
IsAutoupdated bool
|
IsAutoupdated bool
|
||||||
|
|
Loading…
Reference in New Issue