Skip to content

Commit

Permalink
Propagate dns config vales across Headscale
Browse files Browse the repository at this point in the history
  • Loading branch information
juanfont committed Oct 2, 2021
1 parent 5dbf6b5 commit 656237e
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 22 deletions.
16 changes: 5 additions & 11 deletions api.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ func (h *Headscale) getMapResponse(mKey wgkey.Key, req tailcfg.MapRequest, m Mac
Str("func", "getMapResponse").
Str("machine", req.Hostinfo.Hostname).
Msg("Creating Map response")
node, err := m.toNode(true)
node, err := h.toNode(m, true)
if err != nil {
log.Error().
Str("func", "getMapResponse").
Expand All @@ -242,17 +242,11 @@ func (h *Headscale) getMapResponse(mKey wgkey.Key, req tailcfg.MapRequest, m Mac
}

resp := tailcfg.MapResponse{
KeepAlive: false,
Node: node,
Peers: *peers,
//TODO(kradalby): As per tailscale docs, if DNSConfig is nil,
// it means its not updated, maybe we can have some logic
// to check and only pass updates when its updates.
// This is probably more relevant if we try to implement
// "MagicDNS"
KeepAlive: false,
Node: node,
Peers: *peers,
DNSConfig: h.cfg.DNSConfig,
SearchPaths: []string{},
Domain: "headscale.net",
Domain: h.cfg.BaseDomain,
PacketFilter: *h.aclRules,
DERPMap: h.cfg.DerpMap,
UserProfiles: []tailcfg.UserProfile{profile},
Expand Down
1 change: 1 addition & 0 deletions app.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ type Config struct {
DerpMap *tailcfg.DERPMap
EphemeralNodeInactivityTimeout time.Duration
IPPrefix netaddr.IPPrefix
BaseDomain string

DBtype string
DBpath string
Expand Down
18 changes: 13 additions & 5 deletions cmd/headscale/cli/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func LoadConfig(path string) error {

}

func GetDNSConfig() *tailcfg.DNSConfig {
func GetDNSConfig() (*tailcfg.DNSConfig, string) {
if viper.IsSet("dns_config") {
dnsConfig := &tailcfg.DNSConfig{}

Expand Down Expand Up @@ -112,11 +112,16 @@ func GetDNSConfig() *tailcfg.DNSConfig {
dnsConfig.Proxied = viper.GetBool("dns_config.magic_dns")
}

return dnsConfig

var baseDomain string
if viper.IsSet("dns_config.base_domain") {
baseDomain = viper.GetString("dns_config.base_domain")
} else {
baseDomain = "headscale.net" // does not really matter when MagicDNS is not enabled
}
return dnsConfig, baseDomain
}

return nil
return nil, ""
}

func absPath(path string) string {
Expand Down Expand Up @@ -149,12 +154,15 @@ func getHeadscaleApp() (*headscale.Headscale, error) {
return nil, err
}

dnsConfig, baseDomain := GetDNSConfig()

cfg := headscale.Config{
ServerURL: viper.GetString("server_url"),
Addr: viper.GetString("listen_addr"),
PrivateKeyPath: absPath(viper.GetString("private_key_path")),
DerpMap: derpMap,
IPPrefix: netaddr.MustParseIPPrefix(viper.GetString("ip_prefix")),
BaseDomain: baseDomain,

EphemeralNodeInactivityTimeout: viper.GetDuration("ephemeral_node_inactivity_timeout"),

Expand All @@ -174,7 +182,7 @@ func getHeadscaleApp() (*headscale.Headscale, error) {
TLSCertPath: absPath(viper.GetString("tls_cert_path")),
TLSKeyPath: absPath(viper.GetString("tls_key_path")),

DNSConfig: GetDNSConfig(),
DNSConfig: dnsConfig,
}

h, err := headscale.NewHeadscale(cfg)
Expand Down
13 changes: 13 additions & 0 deletions integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,19 @@ func (s *IntegrationTestSuite) TestTailDrop() {
}
}

// func (s *IntegrationTestSuite) TestMagicDNS() {
// for _, scales := range s.namespaces {
// ips, err := getIPs(scales.tailscales)
// assert.Nil(s.T(), err)
// apiURLs, err := getAPIURLs(scales.tailscales)
// assert.Nil(s.T(), err)

// for hostname, tailscale := range scales.tailscales {

// }
// }
// }

func getIPs(tailscales map[string]dockertest.Resource) (map[string]netaddr.IP, error) {
ips := make(map[string]netaddr.IP)
for hostname, tailscale := range tailscales {
Expand Down
14 changes: 9 additions & 5 deletions machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func (m Machine) isAlreadyRegistered() bool {

// toNode converts a Machine into a Tailscale Node. includeRoutes is false for shared nodes
// as per the expected behaviour in the official SaaS
func (m Machine) toNode(includeRoutes bool) (*tailcfg.Node, error) {
func (h *Headscale) toNode(m Machine, includeRoutes bool) (*tailcfg.Node, error) {
nKey, err := wgkey.ParseHex(m.NodeKey)
if err != nil {
return nil, err
Expand Down Expand Up @@ -147,10 +147,12 @@ func (m Machine) toNode(includeRoutes bool) (*tailcfg.Node, error) {
keyExpiry = time.Time{}
}

hostname := fmt.Sprintf("%s.%s.%s", m.Name, m.Namespace.Name, h.cfg.BaseDomain)

n := tailcfg.Node{
ID: tailcfg.NodeID(m.ID), // this is the actual ID
StableID: tailcfg.StableNodeID(strconv.FormatUint(m.ID, 10)), // in headscale, unlike tailcontrol server, IDs are permanent
Name: hostinfo.Hostname,
Name: hostname,
User: tailcfg.UserID(m.NamespaceID),
Key: tailcfg.NodeKey(nKey),
KeyExpiry: keyExpiry,
Expand All @@ -169,6 +171,8 @@ func (m Machine) toNode(includeRoutes bool) (*tailcfg.Node, error) {
MachineAuthorized: m.Registered,
Capabilities: []string{tailcfg.CapabilityFileSharing},
}
// TODO(juanfont): Node also has Sharer when is a shared node with info on the profile

return &n, nil
}

Expand All @@ -179,7 +183,7 @@ func (h *Headscale) getPeers(m Machine) (*[]*tailcfg.Node, error) {
Msg("Finding peers")

machines := []Machine{}
if err := h.db.Where("namespace_id = ? AND machine_key <> ? AND registered",
if err := h.db.Preload("Namespace").Where("namespace_id = ? AND machine_key <> ? AND registered",
m.NamespaceID, m.MachineKey).Find(&machines).Error; err != nil {
log.Error().Err(err).Msg("Error accessing db")
return nil, err
Expand All @@ -194,14 +198,14 @@ func (h *Headscale) getPeers(m Machine) (*[]*tailcfg.Node, error) {

peers := []*tailcfg.Node{}
for _, mn := range machines {
peer, err := mn.toNode(true)
peer, err := h.toNode(mn, true)
if err != nil {
return nil, err
}
peers = append(peers, peer)
}
for _, sharedMachine := range sharedMachines {
peer, err := sharedMachine.Machine.toNode(false) // shared nodes do not expose their routes
peer, err := h.toNode(sharedMachine.Machine, false) // shared nodes do not expose their routes
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion poll.go
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ func (h *Headscale) scheduledPollWorker(
case <-updateCheckerTicker.C:
// Send an update request regardless of outdated or not, if data is sent
// to the node is determined in the updateChan consumer block
n, _ := m.toNode(true)
n, _ := h.toNode(m, true)
err := h.sendRequestOnUpdateChannel(n)
if err != nil {
log.Error().
Expand Down

0 comments on commit 656237e

Please sign in to comment.