only send lite map responses when omitpeers

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
This commit is contained in:
Kristoffer Dalby 2023-07-26 13:55:03 +02:00 committed by Kristoffer Dalby
parent e0ba325b3b
commit e55fe0671a
2 changed files with 104 additions and 59 deletions

View file

@ -124,6 +124,30 @@ func fullMapResponse(
return nil, err return nil, err
} }
now := time.Now()
resp := tailcfg.MapResponse{
Node: tailnode,
DERPMap: derpMap,
Domain: baseDomain,
// Do not instruct clients to collect services we do not
// support or do anything with them
CollectServices: "false",
ControlTime: &now,
KeepAlive: false,
OnlineChange: db.OnlineMachineMap(peers),
Debug: &tailcfg.Debug{
DisableLogTail: !logtail,
RandomizeClientPort: randomClientPort,
},
}
if peers != nil || len(peers) > 0 {
rules, sshPolicy, err := policy.GenerateFilterAndSSHRules( rules, sshPolicy, err := policy.GenerateFilterAndSSHRules(
pol, pol,
machine, machine,
@ -163,35 +187,11 @@ func fullMapResponse(
return tailPeers[x].ID < tailPeers[y].ID return tailPeers[x].ID < tailPeers[y].ID
}) })
now := time.Now() resp.Peers = tailPeers
resp.DNSConfig = dnsConfig
resp := tailcfg.MapResponse{ resp.PacketFilter = policy.ReduceFilterRules(machine, rules)
Node: tailnode, resp.UserProfiles = profiles
Peers: tailPeers, resp.SSHPolicy = sshPolicy
DERPMap: derpMap,
DNSConfig: dnsConfig,
Domain: baseDomain,
// Do not instruct clients to collect services we do not
// support or do anything with them
CollectServices: "false",
PacketFilter: policy.ReduceFilterRules(machine, rules),
UserProfiles: profiles,
SSHPolicy: sshPolicy,
ControlTime: &now,
KeepAlive: false,
OnlineChange: db.OnlineMachineMap(peers),
Debug: &tailcfg.Debug{
DisableLogTail: !logtail,
RandomizeClientPort: randomClientPort,
},
} }
return &resp, nil return &resp, nil
@ -327,6 +327,35 @@ func (m *Mapper) FullMapResponse(
return m.marshalMapResponse(mapResponse, machine, mapRequest.Compress) return m.marshalMapResponse(mapResponse, machine, mapRequest.Compress)
} }
// LiteMapResponse returns a MapResponse for the given machine.
// Lite means that the peers has been omited, this is intended
// to be used to answer MapRequests with OmitPeers set to true.
func (m *Mapper) LiteMapResponse(
mapRequest tailcfg.MapRequest,
machine *types.Machine,
pol *policy.ACLPolicy,
) ([]byte, error) {
mapResponse, err := fullMapResponse(
pol,
machine,
nil,
m.baseDomain,
m.dnsCfg,
m.derpMap,
m.logtail,
m.randomClientPort,
)
if err != nil {
return nil, err
}
if m.isNoise {
return m.marshalMapResponse(mapResponse, machine, mapRequest.Compress)
}
return m.marshalMapResponse(mapResponse, machine, mapRequest.Compress)
}
func (m *Mapper) KeepAliveResponse( func (m *Mapper) KeepAliveResponse(
mapRequest tailcfg.MapRequest, mapRequest tailcfg.MapRequest,
machine *types.Machine, machine *types.Machine,

View file

@ -116,14 +116,6 @@ func (h *Headscale) handlePoll(
return return
} }
mapResp, err := mapp.FullMapResponse(mapRequest, machine, h.ACLPolicy)
if err != nil {
logErr(err, "Failed to create MapResponse")
http.Error(writer, "", http.StatusInternalServerError)
return
}
// We update our peers if the client is not sending ReadOnly in the MapRequest // We update our peers if the client is not sending ReadOnly in the MapRequest
// so we don't distribute its initial request (it comes with // so we don't distribute its initial request (it comes with
// empty endpoints to peers) // empty endpoints to peers)
@ -134,9 +126,17 @@ func (h *Headscale) handlePoll(
if mapRequest.ReadOnly { if mapRequest.ReadOnly {
logInfo("Client is starting up. Probably interested in a DERP map") logInfo("Client is starting up. Probably interested in a DERP map")
mapResp, err := mapp.FullMapResponse(mapRequest, machine, h.ACLPolicy)
if err != nil {
logErr(err, "Failed to create MapResponse")
http.Error(writer, "", http.StatusInternalServerError)
return
}
writer.Header().Set("Content-Type", "application/json; charset=utf-8") writer.Header().Set("Content-Type", "application/json; charset=utf-8")
writer.WriteHeader(http.StatusOK) writer.WriteHeader(http.StatusOK)
_, err := writer.Write(mapResp) _, err = writer.Write(mapResp)
if err != nil { if err != nil {
logErr(err, "Failed to write response") logErr(err, "Failed to write response")
} }
@ -151,9 +151,17 @@ func (h *Headscale) handlePoll(
if mapRequest.OmitPeers && !mapRequest.Stream { if mapRequest.OmitPeers && !mapRequest.Stream {
logInfo("Client sent endpoint update and is ok with a response without peer list") logInfo("Client sent endpoint update and is ok with a response without peer list")
mapResp, err := mapp.LiteMapResponse(mapRequest, machine, h.ACLPolicy)
if err != nil {
logErr(err, "Failed to create MapResponse")
http.Error(writer, "", http.StatusInternalServerError)
return
}
writer.Header().Set("Content-Type", "application/json; charset=utf-8") writer.Header().Set("Content-Type", "application/json; charset=utf-8")
writer.WriteHeader(http.StatusOK) writer.WriteHeader(http.StatusOK)
_, err := writer.Write(mapResp) _, err = writer.Write(mapResp)
if err != nil { if err != nil {
logErr(err, "Failed to write response") logErr(err, "Failed to write response")
} }
@ -183,6 +191,14 @@ func (h *Headscale) handlePoll(
logInfo("Sending initial map") logInfo("Sending initial map")
mapResp, err := mapp.FullMapResponse(mapRequest, machine, h.ACLPolicy)
if err != nil {
logErr(err, "Failed to create MapResponse")
http.Error(writer, "", http.StatusInternalServerError)
return
}
// Send the client an update to make sure we send an initial mapresponse // Send the client an update to make sure we send an initial mapresponse
_, err = writer.Write(mapResp) _, err = writer.Write(mapResp)
if err != nil { if err != nil {