Skip to content

Conversation

@restanrm
Copy link
Contributor

@restanrm restanrm commented Mar 3, 2022

  • read the CONTRIBUTING guidelines
  • raised a GitHub issue or discussed it on the projects chat beforehand
  • [] added unit tests
  • [] added integration tests
  • [] updated documentation if needed
  • [] updated CHANGELOG.md

This will fix #363 by applying normalization on the hostname. This normalization function will lowercase capital letters and replace forbidden chars. If it cannot find a solution it will raise an error on headscale server.

CAPITALNAME => capitalname
HOST Name 1 => host-name-1

restanrm added 2 commits March 3, 2022 23:52
This function is called often. Normalization of the hostname will be written in database.
poll.go Outdated
Msg("Found machine in database")

machine.Name = req.Hostinfo.Hostname
hname, err := NormalizeNamespaceName(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably generalise the name of this function now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps make them two different functions? NormalizeHostname and NormalizeNamespaceName?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm in favor of something generic since hostname and namespace are both part of a FQDN. So NormalizeName or NormalizeDomainName or NormalizeHostname should work too.
I think I'll go with NormalizeName if that's ok with you.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think FQDN makes sense to have in the name, as that is what it is normalising for

Str("hostinfo.name", req.Hostinfo.Hostname).
Err(err)
}
machine.Name = hname
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, doing this here feels kind of wrong, I think doing it here:
https://github.com/juanfont/headscale/blob/main/api.go#L144

Would be more correct, as this is when the machine registers.

However we need a migration path. It could potentially be done in the DB migration, what do you think?

We should probably also make a tracking ticket of a unique constraint for a machine name per user, so we dont have collisions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, that was my first intention. When I found this solution I thought that we could get rid of the need of a database migration, but the --hostname at tailscale up wouldn't work at all.

For the machine name per user I think it would be more a unique name on all the headscale instance. If we tag a machine, this machine should not be accessed by the name of the user that created it (it's currently not implemented).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After re-reading the code. What should we do in this place ? If we keep previous behavior, normalized hostname would be replaced. If we modify in https://github.com/juanfont/headscale/blob/main/api.go#L144 we would not be able to update the hostname with tailscale up --hostname since at line

if errors.Is(err, gorm.ErrRecordNotFound) {
we check that we are only in this section if the machine doesn't already exists.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could migrate all of them on server start up as part of db.go, but that would run everytime :/

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After some tests each time we update the hostname with tailscale up --hostname xxx a call to /machine/:id/map is done. We can also observe the following logs in the tailscaled daemon:

cmd-prometheus1-1  | 2022/03/07 08:49:11 EditPrefs: MaskedPrefs{ControlURL="https://my.redacted.headscale.domain" WantRunning=true Hostname="prometheus2"}
cmd-prometheus1-1  | 2022/03/07 08:49:11 control: HostInfo: {"IPNVersion":"1.22.0-t4e0b00ad8","BackendLogID":"3a5dce2711b4137729be89a95f315ee9ac733cf3a55dd2555c31aac5ab93a328","OS":"linux","OSVersion":"Alpine Linux v3.15; kernel=5.15.2-arch1-1","Hostname":"prometheus2","GoArch":"amd64","Services":[{"Proto":"peerapi4","Port":58436},{"Proto":"peerapi-dns-proxy","Port":1}],"NetInfo":{"MappingVariesByDestIP":false,"HairPinning":false,"WorkingIPv6":false,"WorkingUDP":true,"UPnP":false,"PMP":false,"PCP":false,"PreferredDERP":8,"DERPLatency":{"1-v4":0.088316282,"10-v4":0.158354527,"11-v4":0.237721537,"12-v4":0.099872237,"2-v4":0.15813595,"4-v4":0.026846961,"6-v4":0.224276797,"7-v4":0.254514052,"8-v4":0.018363134,"9-v4":0.121180425}}}
cmd-prometheus1-1  | 2022/03/07 08:49:11 control: PollNetMap: stream=false :0 ep=[90.27.176.219:60654 172.18.0.3:60654]
cmd-prometheus1-1  | 2022/03/07 08:49:11 wgengine: Reconfig done
cmd-prometheus1-1  | 2022/03/07 08:49:11 authReconfig: ra=false dns=true 0x01: <nil>
cmd-prometheus1-1  | 2022/03/07 08:49:11 [unexpected] peerapi listen("fd7a:115c:a1e0::1") error: listen tcp6 [fd7a:115c:a1e0::1]:0: bind: cannot assign requested address
cmd-prometheus1-1  | 2022/03/07 08:49:11 peerapi: serving on http://100.64.0.1:58436

I could not find solid proof in reasonable time from the code of tailscale that each modification of the preference would lead to a NetPollMap call, but it's very likely.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we need it in both places?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that would be better yes !

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets give it a go then :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I'll made the modifications on the name of the function and add this code to both places tonight.

acls.go Outdated
)
}
grp, err := NormalizeNamespaceName(group, stripEmailDomain)
grp, err := NormalizeName(group, stripEmailDomain)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think as mentioned this is a bit to generic, for a unknown user to understand the context, it needs to either have FQDN or Domain or some reference to the RFC and limitations in the name.

@kradalby kradalby merged commit b0ae324 into juanfont:main Mar 8, 2022
@restanrm restanrm deleted the fix-magic-dns-and-uppercase-letters branch March 8, 2022 08:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MagicDNS doesn't register hostnames with upper-case letters

4 participants