feature/conn25: call AuthReconfigAsync after address assignment

When the client of a connector assigns transit IP addresses for a
connector we need to let wireguard know that packets for the transit IPs
should be sent to the connector node. We do this by:
 * keeping a map of node -> transit IPs we've assigned for it
 * setting a callback hook within wireguard reconfig to ask us for these
   extra allowed IPs.
 * forcing wireguard to do a reconfig after we have assigned new transit
   IPs.

And this commit is the last part: forcing the wireguard reconfig after a
new address assignment.

Fixes tailscale/corp#38124

Signed-off-by: Fran Bull <fran@tailscale.com>
main
Fran Bull 4 weeks ago committed by franbull
parent 9c36a71a90
commit 85906b61f4
  1. 13
      feature/conn25/conn25.go
  2. 19
      feature/conn25/conn25_test.go

@ -603,13 +603,22 @@ func (e *extension) sendLoop(ctx context.Context) {
case <-ctx.Done():
return
case as := <-e.conn25.client.addrsCh:
if err := e.sendAddressAssignment(ctx, as); err != nil {
e.conn25.client.logf("error sending transit IP assignment (app: %s, mip: %v, src: %v): %v", as.app, as.magic, as.dst, err)
if err := e.handleAddressAssignment(ctx, as); err != nil {
e.conn25.client.logf("error handling transit IP assignment (app: %s, mip: %v, src: %v): %v", as.app, as.magic, as.dst, err)
}
}
}
}
func (e *extension) handleAddressAssignment(ctx context.Context, as addrs) error {
if err := e.sendAddressAssignment(ctx, as); err != nil {
return err
}
// TODO(fran) assign the connector publickey -> transit ip addresses
e.host.AuthReconfigAsync()
return nil
}
func (c *client) enqueueAddressAssignment(addrs addrs) error {
select {
// TODO(fran) investigate the value of waiting for multiple addresses and sending them

@ -800,10 +800,12 @@ type testHost struct {
ipnext.Host
nb ipnext.NodeBackend
hooks ipnext.Hooks
authReconfigAsync func()
}
func (h *testHost) NodeBackend() ipnext.NodeBackend { return h.nb }
func (h *testHost) Hooks() *ipnext.Hooks { return &h.hooks }
func (h *testHost) AuthReconfigAsync() { h.authReconfigAsync() }
type testSafeBackend struct {
ipnext.SafeBackend
@ -812,9 +814,11 @@ type testSafeBackend struct {
func (b *testSafeBackend) Sys() *tsd.System { return b.sys }
// TestEnqueueAddress tests that after enqueueAddress has been called a
// peerapi request is made to a peer.
func TestEnqueueAddress(t *testing.T) {
// TestAddressAssignmentIsHandled tests that after enqueueAddress has been called
// we handle the assignment asynchronously by:
// - making a peerapi request to a peer.
// - calling AuthReconfigAsync on the host.
func TestAddressAssignmentIsHandled(t *testing.T) {
// make a fake peer to test against
received := make(chan ConnectorTransitIPRequest, 1)
peersAPI := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@ -849,11 +853,15 @@ func TestEnqueueAddress(t *testing.T) {
conn25: newConn25(logger.Discard),
backend: &testSafeBackend{sys: sys},
}
authReconfigAsyncCalled := make(chan struct{}, 1)
if err := ext.Init(&testHost{
nb: &testNodeBackend{
peers: []tailcfg.NodeView{connectorPeer},
peerAPIURL: peersAPI.URL,
},
authReconfigAsync: func() {
authReconfigAsyncCalled <- struct{}{}
},
}); err != nil {
t.Fatal(err)
}
@ -896,6 +904,11 @@ func TestEnqueueAddress(t *testing.T) {
case <-time.After(5 * time.Second):
t.Fatal("timed out waiting for connector to receive request")
}
select {
case <-authReconfigAsyncCalled:
case <-time.After(5 * time.Second):
t.Fatal("timed out waiting for AuthReconfigAsync to be called")
}
}
func parseResponse(t *testing.T, buf []byte) ([]dnsmessage.Resource, []dnsmessage.Resource) {

Loading…
Cancel
Save