mirror of
https://github.com/juanfont/headscale.git
synced 2025-08-05 13:49:57 +02:00
wire through primare router
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
This commit is contained in:
parent
d3bce2d7ff
commit
a48843bfd0
@ -572,7 +572,7 @@ func (h *Headscale) Serve() error {
|
|||||||
|
|
||||||
// Fetch an initial DERP Map before we start serving
|
// Fetch an initial DERP Map before we start serving
|
||||||
h.DERPMap = derp.GetDERPMap(h.cfg.DERP)
|
h.DERPMap = derp.GetDERPMap(h.cfg.DERP)
|
||||||
h.mapper = mapper.NewMapper(h.db, h.cfg, h.DERPMap, h.nodeNotifier, h.polMan)
|
h.mapper = mapper.NewMapper(h.db, h.cfg, h.DERPMap, h.nodeNotifier, h.polMan, h.primaryRoutes)
|
||||||
|
|
||||||
if h.cfg.DERP.ServerEnabled {
|
if h.cfg.DERP.ServerEnabled {
|
||||||
// When embedded DERP is enabled we always need a STUN server
|
// When embedded DERP is enabled we always need a STUN server
|
||||||
|
@ -18,6 +18,7 @@ import (
|
|||||||
"github.com/juanfont/headscale/hscontrol/db"
|
"github.com/juanfont/headscale/hscontrol/db"
|
||||||
"github.com/juanfont/headscale/hscontrol/notifier"
|
"github.com/juanfont/headscale/hscontrol/notifier"
|
||||||
"github.com/juanfont/headscale/hscontrol/policy"
|
"github.com/juanfont/headscale/hscontrol/policy"
|
||||||
|
"github.com/juanfont/headscale/hscontrol/routes"
|
||||||
"github.com/juanfont/headscale/hscontrol/types"
|
"github.com/juanfont/headscale/hscontrol/types"
|
||||||
"github.com/juanfont/headscale/hscontrol/util"
|
"github.com/juanfont/headscale/hscontrol/util"
|
||||||
"github.com/klauspost/compress/zstd"
|
"github.com/klauspost/compress/zstd"
|
||||||
@ -56,6 +57,7 @@ type Mapper struct {
|
|||||||
derpMap *tailcfg.DERPMap
|
derpMap *tailcfg.DERPMap
|
||||||
notif *notifier.Notifier
|
notif *notifier.Notifier
|
||||||
polMan policy.PolicyManager
|
polMan policy.PolicyManager
|
||||||
|
primary *routes.PrimaryRoutes
|
||||||
|
|
||||||
uid string
|
uid string
|
||||||
created time.Time
|
created time.Time
|
||||||
@ -73,6 +75,7 @@ func NewMapper(
|
|||||||
derpMap *tailcfg.DERPMap,
|
derpMap *tailcfg.DERPMap,
|
||||||
notif *notifier.Notifier,
|
notif *notifier.Notifier,
|
||||||
polMan policy.PolicyManager,
|
polMan policy.PolicyManager,
|
||||||
|
primary *routes.PrimaryRoutes,
|
||||||
) *Mapper {
|
) *Mapper {
|
||||||
uid, _ := util.GenerateRandomStringDNSSafe(mapperIDLength)
|
uid, _ := util.GenerateRandomStringDNSSafe(mapperIDLength)
|
||||||
|
|
||||||
@ -82,6 +85,7 @@ func NewMapper(
|
|||||||
derpMap: derpMap,
|
derpMap: derpMap,
|
||||||
notif: notif,
|
notif: notif,
|
||||||
polMan: polMan,
|
polMan: polMan,
|
||||||
|
primary: primary,
|
||||||
|
|
||||||
uid: uid,
|
uid: uid,
|
||||||
created: time.Now(),
|
created: time.Now(),
|
||||||
@ -166,6 +170,7 @@ func (m *Mapper) fullMapResponse(
|
|||||||
resp,
|
resp,
|
||||||
true, // full change
|
true, // full change
|
||||||
m.polMan,
|
m.polMan,
|
||||||
|
m.primary,
|
||||||
node,
|
node,
|
||||||
capVer,
|
capVer,
|
||||||
peers,
|
peers,
|
||||||
@ -271,6 +276,7 @@ func (m *Mapper) PeerChangedResponse(
|
|||||||
&resp,
|
&resp,
|
||||||
false, // partial change
|
false, // partial change
|
||||||
m.polMan,
|
m.polMan,
|
||||||
|
m.primary,
|
||||||
node,
|
node,
|
||||||
mapRequest.Version,
|
mapRequest.Version,
|
||||||
changedNodes,
|
changedNodes,
|
||||||
@ -299,7 +305,7 @@ func (m *Mapper) PeerChangedResponse(
|
|||||||
|
|
||||||
// Add the node itself, it might have changed, and particularly
|
// Add the node itself, it might have changed, and particularly
|
||||||
// if there are no patches or changes, this is a self update.
|
// if there are no patches or changes, this is a self update.
|
||||||
tailnode, err := tailNode(node, mapRequest.Version, m.polMan, m.cfg)
|
tailnode, err := tailNode(node, mapRequest.Version, m.polMan, m.primary, m.cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -446,7 +452,7 @@ func (m *Mapper) baseWithConfigMapResponse(
|
|||||||
) (*tailcfg.MapResponse, error) {
|
) (*tailcfg.MapResponse, error) {
|
||||||
resp := m.baseMapResponse()
|
resp := m.baseMapResponse()
|
||||||
|
|
||||||
tailnode, err := tailNode(node, capVer, m.polMan, m.cfg)
|
tailnode, err := tailNode(node, capVer, m.polMan, m.primary, m.cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -500,6 +506,7 @@ func appendPeerChanges(
|
|||||||
|
|
||||||
fullChange bool,
|
fullChange bool,
|
||||||
polMan policy.PolicyManager,
|
polMan policy.PolicyManager,
|
||||||
|
primary *routes.PrimaryRoutes,
|
||||||
node *types.Node,
|
node *types.Node,
|
||||||
capVer tailcfg.CapabilityVersion,
|
capVer tailcfg.CapabilityVersion,
|
||||||
changed types.Nodes,
|
changed types.Nodes,
|
||||||
@ -522,7 +529,7 @@ func appendPeerChanges(
|
|||||||
|
|
||||||
dnsConfig := generateDNSConfig(cfg, node)
|
dnsConfig := generateDNSConfig(cfg, node)
|
||||||
|
|
||||||
tailPeers, err := tailNodes(changed, capVer, polMan, cfg)
|
tailPeers, err := tailNodes(changed, capVer, polMan, primary, cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -6,10 +6,10 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/davecgh/go-spew/spew"
|
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
"github.com/google/go-cmp/cmp/cmpopts"
|
"github.com/google/go-cmp/cmp/cmpopts"
|
||||||
"github.com/juanfont/headscale/hscontrol/policy"
|
"github.com/juanfont/headscale/hscontrol/policy"
|
||||||
|
"github.com/juanfont/headscale/hscontrol/routes"
|
||||||
"github.com/juanfont/headscale/hscontrol/types"
|
"github.com/juanfont/headscale/hscontrol/types"
|
||||||
"gopkg.in/check.v1"
|
"gopkg.in/check.v1"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
@ -159,11 +159,11 @@ func Test_fullMapResponse(t *testing.T) {
|
|||||||
lastSeen := time.Date(2009, time.November, 10, 23, 9, 0, 0, time.UTC)
|
lastSeen := time.Date(2009, time.November, 10, 23, 9, 0, 0, time.UTC)
|
||||||
expire := time.Date(2500, time.November, 11, 23, 0, 0, 0, time.UTC)
|
expire := time.Date(2500, time.November, 11, 23, 0, 0, 0, time.UTC)
|
||||||
|
|
||||||
user1 := types.User{Model: gorm.Model{ID: 0}, Name: "mini"}
|
user1 := types.User{Model: gorm.Model{ID: 1}, Name: "user1"}
|
||||||
user2 := types.User{Model: gorm.Model{ID: 1}, Name: "peer2"}
|
user2 := types.User{Model: gorm.Model{ID: 2}, Name: "user2"}
|
||||||
|
|
||||||
mini := &types.Node{
|
mini := &types.Node{
|
||||||
ID: 0,
|
ID: 1,
|
||||||
MachineKey: mustMK(
|
MachineKey: mustMK(
|
||||||
"mkey:f08305b4ee4250b95a70f3b7504d048d75d899993c624a26d422c67af0422507",
|
"mkey:f08305b4ee4250b95a70f3b7504d048d75d899993c624a26d422c67af0422507",
|
||||||
),
|
),
|
||||||
@ -194,10 +194,10 @@ func Test_fullMapResponse(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tailMini := &tailcfg.Node{
|
tailMini := &tailcfg.Node{
|
||||||
ID: 0,
|
ID: 1,
|
||||||
StableID: "0",
|
StableID: "1",
|
||||||
Name: "mini",
|
Name: "mini",
|
||||||
User: 0,
|
User: tailcfg.UserID(user1.ID),
|
||||||
Key: mustNK(
|
Key: mustNK(
|
||||||
"nodekey:9b2ffa7e08cc421a3d2cca9012280f6a236fd0de0b4ce005b30a98ad930306fe",
|
"nodekey:9b2ffa7e08cc421a3d2cca9012280f6a236fd0de0b4ce005b30a98ad930306fe",
|
||||||
),
|
),
|
||||||
@ -214,12 +214,17 @@ func Test_fullMapResponse(t *testing.T) {
|
|||||||
tsaddr.AllIPv4(),
|
tsaddr.AllIPv4(),
|
||||||
netip.MustParsePrefix("192.168.0.0/24"),
|
netip.MustParsePrefix("192.168.0.0/24"),
|
||||||
},
|
},
|
||||||
HomeDERP: 0,
|
HomeDERP: 0,
|
||||||
LegacyDERPString: "127.3.3.40:0",
|
LegacyDERPString: "127.3.3.40:0",
|
||||||
Hostinfo: hiview(tailcfg.Hostinfo{}),
|
Hostinfo: hiview(tailcfg.Hostinfo{
|
||||||
|
RoutableIPs: []netip.Prefix{
|
||||||
|
tsaddr.AllIPv4(),
|
||||||
|
netip.MustParsePrefix("192.168.0.0/24"),
|
||||||
|
netip.MustParsePrefix("172.0.0.0/10"),
|
||||||
|
},
|
||||||
|
}),
|
||||||
Created: created,
|
Created: created,
|
||||||
Tags: []string{},
|
Tags: []string{},
|
||||||
PrimaryRoutes: []netip.Prefix{netip.MustParsePrefix("192.168.0.0/24")},
|
|
||||||
LastSeen: &lastSeen,
|
LastSeen: &lastSeen,
|
||||||
MachineAuthorized: true,
|
MachineAuthorized: true,
|
||||||
|
|
||||||
@ -231,7 +236,7 @@ func Test_fullMapResponse(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
peer1 := &types.Node{
|
peer1 := &types.Node{
|
||||||
ID: 1,
|
ID: 2,
|
||||||
MachineKey: mustMK(
|
MachineKey: mustMK(
|
||||||
"mkey:f08305b4ee4250b95a70f3b7504d048d75d899993c624a26d422c67af0422507",
|
"mkey:f08305b4ee4250b95a70f3b7504d048d75d899993c624a26d422c67af0422507",
|
||||||
),
|
),
|
||||||
@ -244,8 +249,8 @@ func Test_fullMapResponse(t *testing.T) {
|
|||||||
IPv4: iap("100.64.0.2"),
|
IPv4: iap("100.64.0.2"),
|
||||||
Hostname: "peer1",
|
Hostname: "peer1",
|
||||||
GivenName: "peer1",
|
GivenName: "peer1",
|
||||||
UserID: user1.ID,
|
UserID: user2.ID,
|
||||||
User: user1,
|
User: user2,
|
||||||
ForcedTags: []string{},
|
ForcedTags: []string{},
|
||||||
LastSeen: &lastSeen,
|
LastSeen: &lastSeen,
|
||||||
Expiry: &expire,
|
Expiry: &expire,
|
||||||
@ -254,9 +259,10 @@ func Test_fullMapResponse(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tailPeer1 := &tailcfg.Node{
|
tailPeer1 := &tailcfg.Node{
|
||||||
ID: 1,
|
ID: 2,
|
||||||
StableID: "1",
|
StableID: "2",
|
||||||
Name: "peer1",
|
Name: "peer1",
|
||||||
|
User: tailcfg.UserID(user2.ID),
|
||||||
Key: mustNK(
|
Key: mustNK(
|
||||||
"nodekey:9b2ffa7e08cc421a3d2cca9012280f6a236fd0de0b4ce005b30a98ad930306fe",
|
"nodekey:9b2ffa7e08cc421a3d2cca9012280f6a236fd0de0b4ce005b30a98ad930306fe",
|
||||||
),
|
),
|
||||||
@ -274,7 +280,6 @@ func Test_fullMapResponse(t *testing.T) {
|
|||||||
Hostinfo: hiview(tailcfg.Hostinfo{}),
|
Hostinfo: hiview(tailcfg.Hostinfo{}),
|
||||||
Created: created,
|
Created: created,
|
||||||
Tags: []string{},
|
Tags: []string{},
|
||||||
PrimaryRoutes: []netip.Prefix{},
|
|
||||||
LastSeen: &lastSeen,
|
LastSeen: &lastSeen,
|
||||||
MachineAuthorized: true,
|
MachineAuthorized: true,
|
||||||
|
|
||||||
@ -285,29 +290,6 @@ func Test_fullMapResponse(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
peer2 := &types.Node{
|
|
||||||
ID: 2,
|
|
||||||
MachineKey: mustMK(
|
|
||||||
"mkey:f08305b4ee4250b95a70f3b7504d048d75d899993c624a26d422c67af0422507",
|
|
||||||
),
|
|
||||||
NodeKey: mustNK(
|
|
||||||
"nodekey:9b2ffa7e08cc421a3d2cca9012280f6a236fd0de0b4ce005b30a98ad930306fe",
|
|
||||||
),
|
|
||||||
DiscoKey: mustDK(
|
|
||||||
"discokey:cf7b0fd05da556fdc3bab365787b506fd82d64a70745db70e00e86c1b1c03084",
|
|
||||||
),
|
|
||||||
IPv4: iap("100.64.0.3"),
|
|
||||||
Hostname: "peer2",
|
|
||||||
GivenName: "peer2",
|
|
||||||
UserID: user2.ID,
|
|
||||||
User: user2,
|
|
||||||
ForcedTags: []string{},
|
|
||||||
LastSeen: &lastSeen,
|
|
||||||
Expiry: &expire,
|
|
||||||
Hostinfo: &tailcfg.Hostinfo{},
|
|
||||||
CreatedAt: created,
|
|
||||||
}
|
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
pol *policy.ACLPolicy
|
pol *policy.ACLPolicy
|
||||||
@ -349,7 +331,7 @@ func Test_fullMapResponse(t *testing.T) {
|
|||||||
Domain: "",
|
Domain: "",
|
||||||
CollectServices: "false",
|
CollectServices: "false",
|
||||||
PacketFilter: []tailcfg.FilterRule{},
|
PacketFilter: []tailcfg.FilterRule{},
|
||||||
UserProfiles: []tailcfg.UserProfile{{LoginName: "mini", DisplayName: "mini"}},
|
UserProfiles: []tailcfg.UserProfile{{ID: tailcfg.UserID(user1.ID), LoginName: "user1", DisplayName: "user1"}},
|
||||||
SSHPolicy: &tailcfg.SSHPolicy{Rules: []*tailcfg.SSHRule{}},
|
SSHPolicy: &tailcfg.SSHPolicy{Rules: []*tailcfg.SSHRule{}},
|
||||||
ControlTime: &time.Time{},
|
ControlTime: &time.Time{},
|
||||||
Debug: &tailcfg.Debug{
|
Debug: &tailcfg.Debug{
|
||||||
@ -383,9 +365,12 @@ func Test_fullMapResponse(t *testing.T) {
|
|||||||
Domain: "",
|
Domain: "",
|
||||||
CollectServices: "false",
|
CollectServices: "false",
|
||||||
PacketFilter: []tailcfg.FilterRule{},
|
PacketFilter: []tailcfg.FilterRule{},
|
||||||
UserProfiles: []tailcfg.UserProfile{{LoginName: "mini", DisplayName: "mini"}},
|
UserProfiles: []tailcfg.UserProfile{
|
||||||
SSHPolicy: &tailcfg.SSHPolicy{Rules: []*tailcfg.SSHRule{}},
|
{ID: tailcfg.UserID(user1.ID), LoginName: "user1", DisplayName: "user1"},
|
||||||
ControlTime: &time.Time{},
|
{ID: tailcfg.UserID(user2.ID), LoginName: "user2", DisplayName: "user2"},
|
||||||
|
},
|
||||||
|
SSHPolicy: &tailcfg.SSHPolicy{Rules: []*tailcfg.SSHRule{}},
|
||||||
|
ControlTime: &time.Time{},
|
||||||
Debug: &tailcfg.Debug{
|
Debug: &tailcfg.Debug{
|
||||||
DisableLogTail: true,
|
DisableLogTail: true,
|
||||||
},
|
},
|
||||||
@ -395,6 +380,9 @@ func Test_fullMapResponse(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "with-pol-map-response",
|
name: "with-pol-map-response",
|
||||||
pol: &policy.ACLPolicy{
|
pol: &policy.ACLPolicy{
|
||||||
|
Hosts: policy.Hosts{
|
||||||
|
"mini": netip.MustParsePrefix("100.64.0.1/32"),
|
||||||
|
},
|
||||||
ACLs: []policy.ACL{
|
ACLs: []policy.ACL{
|
||||||
{
|
{
|
||||||
Action: "accept",
|
Action: "accept",
|
||||||
@ -406,7 +394,6 @@ func Test_fullMapResponse(t *testing.T) {
|
|||||||
node: mini,
|
node: mini,
|
||||||
peers: types.Nodes{
|
peers: types.Nodes{
|
||||||
peer1,
|
peer1,
|
||||||
peer2,
|
|
||||||
},
|
},
|
||||||
derpMap: &tailcfg.DERPMap{},
|
derpMap: &tailcfg.DERPMap{},
|
||||||
cfg: &types.Config{
|
cfg: &types.Config{
|
||||||
@ -434,7 +421,8 @@ func Test_fullMapResponse(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
UserProfiles: []tailcfg.UserProfile{
|
UserProfiles: []tailcfg.UserProfile{
|
||||||
{LoginName: "mini", DisplayName: "mini"},
|
{ID: tailcfg.UserID(user1.ID), LoginName: "user1", DisplayName: "user1"},
|
||||||
|
{ID: tailcfg.UserID(user2.ID), LoginName: "user2", DisplayName: "user2"},
|
||||||
},
|
},
|
||||||
SSHPolicy: &tailcfg.SSHPolicy{Rules: []*tailcfg.SSHRule{}},
|
SSHPolicy: &tailcfg.SSHPolicy{Rules: []*tailcfg.SSHRule{}},
|
||||||
ControlTime: &time.Time{},
|
ControlTime: &time.Time{},
|
||||||
@ -449,6 +437,12 @@ func Test_fullMapResponse(t *testing.T) {
|
|||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
polMan, _ := policy.NewPolicyManagerForTest(tt.pol, []types.User{user1, user2}, append(tt.peers, tt.node))
|
polMan, _ := policy.NewPolicyManagerForTest(tt.pol, []types.User{user1, user2}, append(tt.peers, tt.node))
|
||||||
|
primary := routes.New()
|
||||||
|
|
||||||
|
primary.RegisterRoutes(tt.node.ID, tt.node.SubnetRoutes()...)
|
||||||
|
for _, peer := range tt.peers {
|
||||||
|
primary.RegisterRoutes(peer.ID, peer.SubnetRoutes()...)
|
||||||
|
}
|
||||||
|
|
||||||
mappy := NewMapper(
|
mappy := NewMapper(
|
||||||
nil,
|
nil,
|
||||||
@ -456,6 +450,7 @@ func Test_fullMapResponse(t *testing.T) {
|
|||||||
tt.derpMap,
|
tt.derpMap,
|
||||||
nil,
|
nil,
|
||||||
polMan,
|
polMan,
|
||||||
|
primary,
|
||||||
)
|
)
|
||||||
|
|
||||||
got, err := mappy.fullMapResponse(
|
got, err := mappy.fullMapResponse(
|
||||||
@ -470,8 +465,6 @@ func Test_fullMapResponse(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
spew.Dump(got)
|
|
||||||
|
|
||||||
if diff := cmp.Diff(
|
if diff := cmp.Diff(
|
||||||
tt.want,
|
tt.want,
|
||||||
got,
|
got,
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/juanfont/headscale/hscontrol/policy"
|
"github.com/juanfont/headscale/hscontrol/policy"
|
||||||
|
"github.com/juanfont/headscale/hscontrol/routes"
|
||||||
"github.com/juanfont/headscale/hscontrol/types"
|
"github.com/juanfont/headscale/hscontrol/types"
|
||||||
"github.com/samber/lo"
|
"github.com/samber/lo"
|
||||||
"tailscale.com/tailcfg"
|
"tailscale.com/tailcfg"
|
||||||
@ -15,6 +16,7 @@ func tailNodes(
|
|||||||
nodes types.Nodes,
|
nodes types.Nodes,
|
||||||
capVer tailcfg.CapabilityVersion,
|
capVer tailcfg.CapabilityVersion,
|
||||||
polMan policy.PolicyManager,
|
polMan policy.PolicyManager,
|
||||||
|
primary *routes.PrimaryRoutes,
|
||||||
cfg *types.Config,
|
cfg *types.Config,
|
||||||
) ([]*tailcfg.Node, error) {
|
) ([]*tailcfg.Node, error) {
|
||||||
tNodes := make([]*tailcfg.Node, len(nodes))
|
tNodes := make([]*tailcfg.Node, len(nodes))
|
||||||
@ -24,6 +26,7 @@ func tailNodes(
|
|||||||
node,
|
node,
|
||||||
capVer,
|
capVer,
|
||||||
polMan,
|
polMan,
|
||||||
|
primary,
|
||||||
cfg,
|
cfg,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -41,6 +44,7 @@ func tailNode(
|
|||||||
node *types.Node,
|
node *types.Node,
|
||||||
capVer tailcfg.CapabilityVersion,
|
capVer tailcfg.CapabilityVersion,
|
||||||
polMan policy.PolicyManager,
|
polMan policy.PolicyManager,
|
||||||
|
primary *routes.PrimaryRoutes,
|
||||||
cfg *types.Config,
|
cfg *types.Config,
|
||||||
) (*tailcfg.Node, error) {
|
) (*tailcfg.Node, error) {
|
||||||
addrs := node.Prefixes()
|
addrs := node.Prefixes()
|
||||||
@ -94,6 +98,7 @@ func tailNode(
|
|||||||
Machine: node.MachineKey,
|
Machine: node.MachineKey,
|
||||||
DiscoKey: node.DiscoKey,
|
DiscoKey: node.DiscoKey,
|
||||||
Addresses: addrs,
|
Addresses: addrs,
|
||||||
|
PrimaryRoutes: primary.PrimaryRoutes(node.ID),
|
||||||
AllowedIPs: allowedIPs,
|
AllowedIPs: allowedIPs,
|
||||||
Endpoints: node.Endpoints,
|
Endpoints: node.Endpoints,
|
||||||
HomeDERP: derp,
|
HomeDERP: derp,
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
"github.com/google/go-cmp/cmp/cmpopts"
|
"github.com/google/go-cmp/cmp/cmpopts"
|
||||||
"github.com/juanfont/headscale/hscontrol/policy"
|
"github.com/juanfont/headscale/hscontrol/policy"
|
||||||
|
"github.com/juanfont/headscale/hscontrol/routes"
|
||||||
"github.com/juanfont/headscale/hscontrol/types"
|
"github.com/juanfont/headscale/hscontrol/types"
|
||||||
"tailscale.com/net/tsaddr"
|
"tailscale.com/net/tsaddr"
|
||||||
"tailscale.com/tailcfg"
|
"tailscale.com/tailcfg"
|
||||||
@ -72,7 +73,6 @@ func TestTailNode(t *testing.T) {
|
|||||||
LegacyDERPString: "127.3.3.40:0",
|
LegacyDERPString: "127.3.3.40:0",
|
||||||
Hostinfo: hiview(tailcfg.Hostinfo{}),
|
Hostinfo: hiview(tailcfg.Hostinfo{}),
|
||||||
Tags: []string{},
|
Tags: []string{},
|
||||||
PrimaryRoutes: []netip.Prefix{},
|
|
||||||
MachineAuthorized: true,
|
MachineAuthorized: true,
|
||||||
|
|
||||||
CapMap: tailcfg.NodeCapMap{
|
CapMap: tailcfg.NodeCapMap{
|
||||||
@ -146,8 +146,14 @@ func TestTailNode(t *testing.T) {
|
|||||||
},
|
},
|
||||||
HomeDERP: 0,
|
HomeDERP: 0,
|
||||||
LegacyDERPString: "127.3.3.40:0",
|
LegacyDERPString: "127.3.3.40:0",
|
||||||
Hostinfo: hiview(tailcfg.Hostinfo{}),
|
Hostinfo: hiview(tailcfg.Hostinfo{
|
||||||
Created: created,
|
RoutableIPs: []netip.Prefix{
|
||||||
|
tsaddr.AllIPv4(),
|
||||||
|
netip.MustParsePrefix("192.168.0.0/24"),
|
||||||
|
netip.MustParsePrefix("172.0.0.0/10"),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
Created: created,
|
||||||
|
|
||||||
Tags: []string{},
|
Tags: []string{},
|
||||||
|
|
||||||
@ -174,15 +180,22 @@ func TestTailNode(t *testing.T) {
|
|||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
polMan, _ := policy.NewPolicyManagerForTest(tt.pol, []types.User{}, types.Nodes{tt.node})
|
polMan, _ := policy.NewPolicyManagerForTest(tt.pol, []types.User{}, types.Nodes{tt.node})
|
||||||
|
primary := routes.New()
|
||||||
cfg := &types.Config{
|
cfg := &types.Config{
|
||||||
BaseDomain: tt.baseDomain,
|
BaseDomain: tt.baseDomain,
|
||||||
TailcfgDNSConfig: tt.dnsConfig,
|
TailcfgDNSConfig: tt.dnsConfig,
|
||||||
RandomizeClientPort: false,
|
RandomizeClientPort: false,
|
||||||
}
|
}
|
||||||
|
_ = primary.RegisterRoutes(tt.node.ID, tt.node.SubnetRoutes()...)
|
||||||
|
|
||||||
|
// This is a hack to avoid having a second node to test the primary route.
|
||||||
|
// This should be baked into the test case proper if it is extended in the future.
|
||||||
|
_ = primary.RegisterRoutes(2, netip.MustParsePrefix("192.168.0.0/24"))
|
||||||
got, err := tailNode(
|
got, err := tailNode(
|
||||||
tt.node,
|
tt.node,
|
||||||
0,
|
0,
|
||||||
polMan,
|
polMan,
|
||||||
|
primary,
|
||||||
cfg,
|
cfg,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -236,6 +249,7 @@ func TestNodeExpiry(t *testing.T) {
|
|||||||
node,
|
node,
|
||||||
0,
|
0,
|
||||||
&policy.PolicyManagerV1{},
|
&policy.PolicyManagerV1{},
|
||||||
|
nil,
|
||||||
&types.Config{},
|
&types.Config{},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -208,6 +208,7 @@ func (pol *ACLPolicy) CompileFilterRules(
|
|||||||
users,
|
users,
|
||||||
alias,
|
alias,
|
||||||
)
|
)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -243,6 +244,7 @@ func (pol *ACLPolicy) CompileFilterRules(
|
|||||||
// ReduceFilterRules takes a node and a set of rules and removes all rules and destinations
|
// ReduceFilterRules takes a node and a set of rules and removes all rules and destinations
|
||||||
// that are not relevant to that particular node.
|
// that are not relevant to that particular node.
|
||||||
func ReduceFilterRules(node *types.Node, rules []tailcfg.FilterRule) []tailcfg.FilterRule {
|
func ReduceFilterRules(node *types.Node, rules []tailcfg.FilterRule) []tailcfg.FilterRule {
|
||||||
|
// TODO(kradalby): Make this nil and not alloc unless needed
|
||||||
ret := []tailcfg.FilterRule{}
|
ret := []tailcfg.FilterRule{}
|
||||||
|
|
||||||
for _, rule := range rules {
|
for _, rule := range rules {
|
||||||
@ -264,13 +266,11 @@ func ReduceFilterRules(node *types.Node, rules []tailcfg.FilterRule) []tailcfg.F
|
|||||||
|
|
||||||
// If the node exposes routes, ensure they are note removed
|
// If the node exposes routes, ensure they are note removed
|
||||||
// when the filters are reduced.
|
// when the filters are reduced.
|
||||||
if node.Hostinfo != nil {
|
if len(node.SubnetRoutes()) > 0 {
|
||||||
if len(node.Hostinfo.RoutableIPs) > 0 {
|
for _, routableIP := range node.SubnetRoutes() {
|
||||||
for _, routableIP := range node.Hostinfo.RoutableIPs {
|
if expanded.OverlapsPrefix(routableIP) {
|
||||||
if expanded.OverlapsPrefix(routableIP) {
|
dests = append(dests, dest)
|
||||||
dests = append(dests, dest)
|
continue DEST_LOOP
|
||||||
continue DEST_LOOP
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ import (
|
|||||||
"net/netip"
|
"net/netip"
|
||||||
"slices"
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
v1 "github.com/juanfont/headscale/gen/go/headscale/v1"
|
v1 "github.com/juanfont/headscale/gen/go/headscale/v1"
|
||||||
@ -108,9 +107,7 @@ type Node struct {
|
|||||||
IsOnline *bool `gorm:"-"`
|
IsOnline *bool `gorm:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type (
|
type Nodes []*Node
|
||||||
Nodes []*Node
|
|
||||||
)
|
|
||||||
|
|
||||||
// GivenNameHasBeenChanged returns whether the `givenName` can be automatically changed based on the `Hostname` of the node.
|
// GivenNameHasBeenChanged returns whether the `givenName` can be automatically changed based on the `Hostname` of the node.
|
||||||
func (node *Node) GivenNameHasBeenChanged() bool {
|
func (node *Node) GivenNameHasBeenChanged() bool {
|
||||||
|
@ -74,3 +74,21 @@ func TailMapResponseToString(resp tailcfg.MapResponse) string {
|
|||||||
TailNodesToString(resp.Peers),
|
TailNodesToString(resp.Peers),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TailcfgFilterRulesToString(rules []tailcfg.FilterRule) string {
|
||||||
|
var sb strings.Builder
|
||||||
|
|
||||||
|
for index, rule := range rules {
|
||||||
|
sb.WriteString(fmt.Sprintf(`
|
||||||
|
{
|
||||||
|
SrcIPs: %v
|
||||||
|
DstIPs: %v
|
||||||
|
}
|
||||||
|
`, rule.SrcIPs, rule.DstPorts))
|
||||||
|
if index < len(rules)-1 {
|
||||||
|
sb.WriteString(", ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("[ %s ](%d)", sb.String(), len(rules))
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user