only send lite map responses when omitpeers
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
This commit is contained in:
parent
e0ba325b3b
commit
e55fe0671a
2 changed files with 104 additions and 59 deletions
|
@ -124,66 +124,19 @@ func fullMapResponse(
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
rules, sshPolicy, err := policy.GenerateFilterAndSSHRules(
|
|
||||||
pol,
|
|
||||||
machine,
|
|
||||||
peers,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter out peers that have expired.
|
|
||||||
peers = lo.Filter(peers, func(item types.Machine, index int) bool {
|
|
||||||
return !item.IsExpired()
|
|
||||||
})
|
|
||||||
|
|
||||||
// If there are filter rules present, see if there are any machines that cannot
|
|
||||||
// access eachother at all and remove them from the peers.
|
|
||||||
if len(rules) > 0 {
|
|
||||||
peers = policy.FilterMachinesByACL(machine, peers, rules)
|
|
||||||
}
|
|
||||||
|
|
||||||
profiles := generateUserProfiles(machine, peers, baseDomain)
|
|
||||||
|
|
||||||
dnsConfig := generateDNSConfig(
|
|
||||||
dnsCfg,
|
|
||||||
baseDomain,
|
|
||||||
*machine,
|
|
||||||
peers,
|
|
||||||
)
|
|
||||||
|
|
||||||
tailPeers, err := tailNodes(peers, pol, dnsCfg, baseDomain)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Peers is always returned sorted by Node.ID.
|
|
||||||
sort.SliceStable(tailPeers, func(x, y int) bool {
|
|
||||||
return tailPeers[x].ID < tailPeers[y].ID
|
|
||||||
})
|
|
||||||
|
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
|
|
||||||
resp := tailcfg.MapResponse{
|
resp := tailcfg.MapResponse{
|
||||||
Node: tailnode,
|
Node: tailnode,
|
||||||
Peers: tailPeers,
|
|
||||||
|
|
||||||
DERPMap: derpMap,
|
DERPMap: derpMap,
|
||||||
|
|
||||||
DNSConfig: dnsConfig,
|
Domain: baseDomain,
|
||||||
Domain: baseDomain,
|
|
||||||
|
|
||||||
// Do not instruct clients to collect services we do not
|
// Do not instruct clients to collect services we do not
|
||||||
// support or do anything with them
|
// support or do anything with them
|
||||||
CollectServices: "false",
|
CollectServices: "false",
|
||||||
|
|
||||||
PacketFilter: policy.ReduceFilterRules(machine, rules),
|
|
||||||
|
|
||||||
UserProfiles: profiles,
|
|
||||||
|
|
||||||
SSHPolicy: sshPolicy,
|
|
||||||
|
|
||||||
ControlTime: &now,
|
ControlTime: &now,
|
||||||
KeepAlive: false,
|
KeepAlive: false,
|
||||||
OnlineChange: db.OnlineMachineMap(peers),
|
OnlineChange: db.OnlineMachineMap(peers),
|
||||||
|
@ -194,6 +147,53 @@ func fullMapResponse(
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if peers != nil || len(peers) > 0 {
|
||||||
|
rules, sshPolicy, err := policy.GenerateFilterAndSSHRules(
|
||||||
|
pol,
|
||||||
|
machine,
|
||||||
|
peers,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter out peers that have expired.
|
||||||
|
peers = lo.Filter(peers, func(item types.Machine, index int) bool {
|
||||||
|
return !item.IsExpired()
|
||||||
|
})
|
||||||
|
|
||||||
|
// If there are filter rules present, see if there are any machines that cannot
|
||||||
|
// access eachother at all and remove them from the peers.
|
||||||
|
if len(rules) > 0 {
|
||||||
|
peers = policy.FilterMachinesByACL(machine, peers, rules)
|
||||||
|
}
|
||||||
|
|
||||||
|
profiles := generateUserProfiles(machine, peers, baseDomain)
|
||||||
|
|
||||||
|
dnsConfig := generateDNSConfig(
|
||||||
|
dnsCfg,
|
||||||
|
baseDomain,
|
||||||
|
*machine,
|
||||||
|
peers,
|
||||||
|
)
|
||||||
|
|
||||||
|
tailPeers, err := tailNodes(peers, pol, dnsCfg, baseDomain)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Peers is always returned sorted by Node.ID.
|
||||||
|
sort.SliceStable(tailPeers, func(x, y int) bool {
|
||||||
|
return tailPeers[x].ID < tailPeers[y].ID
|
||||||
|
})
|
||||||
|
|
||||||
|
resp.Peers = tailPeers
|
||||||
|
resp.DNSConfig = dnsConfig
|
||||||
|
resp.PacketFilter = policy.ReduceFilterRules(machine, rules)
|
||||||
|
resp.UserProfiles = profiles
|
||||||
|
resp.SSHPolicy = sshPolicy
|
||||||
|
}
|
||||||
|
|
||||||
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,
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in a new issue