mirror of
				https://github.com/juanfont/headscale.git
				synced 2025-10-28 10:51:44 +01:00 
			
		
		
		
	only send lite map responses when omitpeers
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
This commit is contained in:
		
							parent
							
								
									e0ba325b3b
								
							
						
					
					
						commit
						e55fe0671a
					
				| @ -124,66 +124,19 @@ func fullMapResponse( | ||||
| 		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() | ||||
| 
 | ||||
| 	resp := tailcfg.MapResponse{ | ||||
| 		Node:  tailnode, | ||||
| 		Peers: tailPeers, | ||||
| 		Node: tailnode, | ||||
| 
 | ||||
| 		DERPMap: derpMap, | ||||
| 
 | ||||
| 		DNSConfig: dnsConfig, | ||||
| 		Domain:    baseDomain, | ||||
| 		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), | ||||
| @ -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 | ||||
| } | ||||
| 
 | ||||
| @ -327,6 +327,35 @@ func (m *Mapper) FullMapResponse( | ||||
| 	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( | ||||
| 	mapRequest tailcfg.MapRequest, | ||||
| 	machine *types.Machine, | ||||
|  | ||||
| @ -116,14 +116,6 @@ func (h *Headscale) handlePoll( | ||||
| 		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
 | ||||
| 	// so we don't distribute its initial request (it comes with
 | ||||
| 	// empty endpoints to peers)
 | ||||
| @ -134,9 +126,17 @@ func (h *Headscale) handlePoll( | ||||
| 	if mapRequest.ReadOnly { | ||||
| 		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.WriteHeader(http.StatusOK) | ||||
| 		_, err := writer.Write(mapResp) | ||||
| 		_, err = writer.Write(mapResp) | ||||
| 		if err != nil { | ||||
| 			logErr(err, "Failed to write response") | ||||
| 		} | ||||
| @ -151,9 +151,17 @@ func (h *Headscale) handlePoll( | ||||
| 	if mapRequest.OmitPeers && !mapRequest.Stream { | ||||
| 		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.WriteHeader(http.StatusOK) | ||||
| 		_, err := writer.Write(mapResp) | ||||
| 		_, err = writer.Write(mapResp) | ||||
| 		if err != nil { | ||||
| 			logErr(err, "Failed to write response") | ||||
| 		} | ||||
| @ -183,6 +191,14 @@ func (h *Headscale) handlePoll( | ||||
| 
 | ||||
| 	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
 | ||||
| 	_, err = writer.Write(mapResp) | ||||
| 	if err != nil { | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user