Skip to content

Use peer's wireguard port, not our own #2200

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions pkg/backend/wireguard/wireguard.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,17 @@ func New(sm subnet.Manager, extIface *backend.ExternalInterface) (backend.Backen
return be, nil
}

func newSubnetAttrs(publicIP net.IP, publicIPv6 net.IP, enableIPv4, enableIPv6 bool, publicKey string) (*lease.LeaseAttrs, error) {
data, err := json.Marshal(&wireguardLeaseAttrs{
func newSubnetAttrs(publicIP net.IP, publicIPv6 net.IP, enableIPv4, enableIPv6 bool, publicKey string, v4Port, v6Port uint16) (*lease.LeaseAttrs, error) {
v4Data, err := json.Marshal(&wireguardLeaseAttrs{
PublicKey: publicKey,
Port: v4Port,
})
if err != nil {
return nil, err
}
v6Data, err := json.Marshal(&wireguardLeaseAttrs{
PublicKey: publicKey,
Port: v6Port,
})
if err != nil {
return nil, err
Expand All @@ -74,15 +82,15 @@ func newSubnetAttrs(publicIP net.IP, publicIPv6 net.IP, enableIPv4, enableIPv6 b
}

if enableIPv4 {
leaseAttrs.BackendData = json.RawMessage(data)
leaseAttrs.BackendData = json.RawMessage(v4Data)
}

if publicIPv6 != nil {
leaseAttrs.PublicIPv6 = ip.FromIP6(publicIPv6)
}

if enableIPv6 {
leaseAttrs.BackendV6Data = json.RawMessage(data)
leaseAttrs.BackendV6Data = json.RawMessage(v6Data)
}

return leaseAttrs, nil
Expand Down Expand Up @@ -155,7 +163,7 @@ func (be *WireguardBackend) RegisterNetwork(ctx context.Context, wg *sync.WaitGr
return nil, fmt.Errorf("no valid Mode configured")
}

subnetAttrs, err := newSubnetAttrs(be.extIface.ExtAddr, be.extIface.ExtV6Addr, config.EnableIPv4, config.EnableIPv6, publicKey)
subnetAttrs, err := newSubnetAttrs(be.extIface.ExtAddr, be.extIface.ExtV6Addr, config.EnableIPv4, config.EnableIPv6, publicKey, uint16(cfg.ListenPort), uint16(cfg.ListenPortV6))
if err != nil {
return nil, err
}
Expand Down
70 changes: 39 additions & 31 deletions pkg/backend/wireguard/wireguard_network.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,10 @@ func (n *network) Run(ctx context.Context) {

type wireguardLeaseAttrs struct {
PublicKey string
Port uint16
}

// Select the endpoint address that is most likely to allow for a successful
// connection.
// Select the mode that is most likely to allow for a successful connection.
// If both ipv4 and ipv6 addresses are provided:
// - Prefer ipv4 if the remote endpoint has a public ipv4 address
// and the external iface has an ipv4 address as well. Anything with
Expand All @@ -115,24 +115,17 @@ type wireguardLeaseAttrs struct {
// address will only have a small chance of succeeding (ipv6 masquarading is
// very rare)
// - If neither is true default to ipv4 and cross fingers.
func (n *network) selectPublicEndpoint(ip4 *ip.IP4, ip6 *ip.IP6) string {
if ip4 != nil && ip6 == nil {
return ip4.String()
func (n *network) selectMode(ip4 ip.IP4, ip6 *ip.IP6) Mode {
if ip6 == nil {
return Ipv4
}

if ip4 == nil && ip6 != nil {
return fmt.Sprintf("[%s]", ip6.String())
}
Comment on lines -119 to -125
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ip4 == nil / != nil stuff got removed because this method is always called as selectPublicEndpoint(&PublicIP ... which of course means ipv4 can't ever be nil, so that check wasn't doing anything.

Dropping it simplifies the logic a bit.

Before, we were also always using the ipv4 port, no matter the ip we pulled out, so I fixed that too.


if !ip4.IsPrivate() && n.extIface.ExtAddr != nil {
return ip4.String()
return Ipv4
}

if !ip6.IsPrivate() && n.extIface.ExtV6Addr != nil && !ip.FromIP6(n.extIface.ExtV6Addr).IsPrivate() {
return fmt.Sprintf("[%s]", ip6.String())
return Ipv6
}

return ip4.String()
return Ipv4
}

func (n *network) handleSubnetEvents(ctx context.Context, batch []lease.Event) {
Expand All @@ -155,7 +148,7 @@ func (n *network) handleSubnetEvents(ctx context.Context, batch []lease.Event) {
}
}
wireguardAttrs = v4wireguardAttrs
subnets = append(subnets, event.Lease.Subnet.ToIPNet()) //only used if n.mode != Separate
subnets = append(subnets, event.Lease.Subnet.ToIPNet()) // only used if n.mode != Separate
}

if event.Lease.EnableIPv6 {
Expand All @@ -166,15 +159,30 @@ func (n *network) handleSubnetEvents(ctx context.Context, batch []lease.Event) {
}
}
wireguardAttrs = v6wireguardAttrs
subnets = append(subnets, event.Lease.IPv6Subnet.ToIPNet()) //only used if n.mode != Separate
subnets = append(subnets, event.Lease.IPv6Subnet.ToIPNet()) // only used if n.mode != Separate
}

// default to the port in the attr, but use the device's listen port
// if it's not set for backwards compatibility with older flannel
// versions.
v4Port := v4wireguardAttrs.Port
if v4Port == 0 && n.dev != nil {
v4Port = uint16(n.dev.attrs.listenPort)
}
v6Port := v6wireguardAttrs.Port
if v6Port == 0 && n.v6Dev != nil {
v6Port = uint16(n.v6Dev.attrs.listenPort)
}
v4PeerEndpoint := fmt.Sprintf("%s:%d", event.Lease.Attrs.PublicIP.String(), v4Port)
var v6PeerEndpoint string
if event.Lease.Attrs.PublicIPv6 != nil {
v6PeerEndpoint = fmt.Sprintf("[%s]:%d", event.Lease.Attrs.PublicIPv6.String(), v6Port)
}
if n.mode == Separate {
if event.Lease.EnableIPv4 {
publicEndpoint := fmt.Sprintf("%s:%d", event.Lease.Attrs.PublicIP.String(), n.dev.attrs.listenPort)
log.Infof("Subnet added: %v via %v", event.Lease.Subnet, publicEndpoint)
log.Infof("Subnet added: %v via %v", event.Lease.Subnet, v4PeerEndpoint)
if err := n.dev.addPeer(
publicEndpoint,
v4PeerEndpoint,
v4wireguardAttrs.PublicKey,
[]net.IPNet{*event.Lease.Subnet.ToIPNet()}); err != nil {
log.Errorf("failed to setup ipv4 peer (%s): %v", v4wireguardAttrs.PublicKey, err)
Expand All @@ -190,10 +198,9 @@ func (n *network) handleSubnetEvents(ctx context.Context, batch []lease.Event) {
}

if event.Lease.EnableIPv6 {
publicEndpoint := fmt.Sprintf("[%s]:%d", event.Lease.Attrs.PublicIPv6.String(), n.v6Dev.attrs.listenPort)
log.Infof("Subnet added: %v via %v", event.Lease.IPv6Subnet, publicEndpoint)
log.Infof("Subnet added: %v via %v", event.Lease.IPv6Subnet, v6PeerEndpoint)
if err := n.v6Dev.addPeer(
publicEndpoint,
v6PeerEndpoint,
v6wireguardAttrs.PublicKey,
[]net.IPNet{*event.Lease.IPv6Subnet.ToIPNet()}); err != nil {
log.Errorf("failed to setup ipv6 peer (%s): %v", v6wireguardAttrs.PublicKey, err)
Expand All @@ -209,14 +216,15 @@ func (n *network) handleSubnetEvents(ctx context.Context, batch []lease.Event) {
}
} else {
var publicEndpoint string
if n.mode == Ipv4 {
publicEndpoint = fmt.Sprintf("%s:%d", event.Lease.Attrs.PublicIP.String(), n.dev.attrs.listenPort)
} else if n.mode == Ipv6 {
publicEndpoint = fmt.Sprintf("[%s]:%d", event.Lease.Attrs.PublicIPv6.String(), n.dev.attrs.listenPort)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line had an additional bug of using the ipv6 IP + ipv4 port, so I think this probably wouldn't generally work.

} else { // Auto mode
publicEndpoint = fmt.Sprintf("%s:%d",
n.selectPublicEndpoint(&event.Lease.Attrs.PublicIP, event.Lease.Attrs.PublicIPv6),
n.dev.attrs.listenPort)
mode := n.mode
if mode != Ipv4 && mode != Ipv6 { // Auto mode
mode = n.selectMode(event.Lease.Attrs.PublicIP, event.Lease.Attrs.PublicIPv6)
}
switch mode {
case Ipv4:
publicEndpoint = v4PeerEndpoint
case Ipv6:
publicEndpoint = v6PeerEndpoint
}

log.Infof("Subnet(s) added: %v via %v", subnets, publicEndpoint)
Expand Down
Loading