Compare commits
6 Commits
cbbf71b759
...
527283e5bd
Author | SHA1 | Date |
---|---|---|
Julian | 527283e5bd | |
Dan Pastusek | 2bac80cfbf | |
Michael Savage | 93a915c096 | |
Julian Mundhahs | c6593a2bcb | |
Julian Mundhahs | 31ee9bb4a8 | |
Julian Mundhahs | 04c7c5b0b6 |
|
@ -20,17 +20,19 @@ configuration (`/etc/headscale/config.yaml`).
|
|||
|
||||
## Installation
|
||||
|
||||
1. Download the latest Headscale package for your platform (`.deb` for Ubuntu and Debian) from [Headscale's releases page](https://github.com/juanfont/headscale/releases):
|
||||
1. Download the [latest Headscale package](https://github.com/juanfont/headscale/releases/latest) for your platform (`.deb` for Ubuntu and Debian).
|
||||
|
||||
```shell
|
||||
HEADSCALE_VERSION="" # See above URL for latest version, e.g. "X.Y.Z" (NOTE: do not add the "v" prefix!)
|
||||
HEADSCALE_ARCH="" # Your system architecture, e.g. "amd64"
|
||||
wget --output-document=headscale.deb \
|
||||
https://github.com/juanfont/headscale/releases/download/v<HEADSCALE VERSION>/headscale_<HEADSCALE VERSION>_linux_<ARCH>.deb
|
||||
"https://github.com/juanfont/headscale/releases/download/v${HEADSCALE_VERSION}/headscale_${HEADSCALE_VERSION}_linux_${HEADSCALE_ARCH}.deb"
|
||||
```
|
||||
|
||||
1. Install Headscale:
|
||||
|
||||
```shell
|
||||
sudo apt install headscale.deb
|
||||
sudo apt install ./headscale.deb
|
||||
```
|
||||
|
||||
1. Enable Headscale service, this will start Headscale at boot:
|
||||
|
|
|
@ -9,19 +9,17 @@
|
|||
|
||||
## Goal
|
||||
|
||||
This documentation has the goal of showing a user how-to install and run `headscale` on OpenBSD 7.1.
|
||||
This documentation has the goal of showing a user how-to install and run `headscale` on OpenBSD.
|
||||
In additional to the "get up and running section", there is an optional [rc.d section](#running-headscale-in-the-background-with-rcd)
|
||||
describing how to make `headscale` run properly in a server environment.
|
||||
|
||||
## Install `headscale`
|
||||
|
||||
1. Install from ports (not recommended)
|
||||
1. Install from ports
|
||||
|
||||
!!! info
|
||||
You can install headscale from ports by running `pkg_add headscale`.
|
||||
|
||||
As of OpenBSD 7.2, there's a headscale in ports collection, however, it's severely outdated(v0.12.4). You can install it via `pkg_add headscale`.
|
||||
|
||||
1. Install from source on OpenBSD 7.2
|
||||
1. Install from source
|
||||
|
||||
```shell
|
||||
# Install prerequistes
|
||||
|
|
|
@ -357,6 +357,31 @@ func (pol *ACLPolicy) CompileSSHPolicy(
|
|||
return nil, fmt.Errorf("parsing SSH policy, unknown action %q, index: %d: %w", sshACL.Action, index, err)
|
||||
}
|
||||
|
||||
recs := make([]netip.AddrPort, 0)
|
||||
for innerIndex, rec := range sshACL.Recorder {
|
||||
recSet, err := pol.ExpandAlias(append(peers, node), rec)
|
||||
if err != nil {
|
||||
log.Error().
|
||||
Msgf("Error parsing SSH %d, Recorder %d", index, innerIndex)
|
||||
return nil, err
|
||||
}
|
||||
// ExpandAlias has expanded possible subnets; all prefixes are single IPs
|
||||
for _, rec := range recSet.Prefixes() {
|
||||
recs = append(recs, netip.AddrPortFrom(rec.Addr(), 80))
|
||||
}
|
||||
}
|
||||
if len(recs) > 0 {
|
||||
action.Message = "# This session is being recorded.\n"
|
||||
}
|
||||
action.Recorders = recs
|
||||
|
||||
if sshACL.EnforceRecorder {
|
||||
action.OnRecordingFailure = &tailcfg.SSHRecorderFailureAction{
|
||||
RejectSessionWithMessage: "# Failed to start session recording.",
|
||||
TerminateSessionWithMessage: "# Failed to start session recording.",
|
||||
}
|
||||
}
|
||||
|
||||
principals := make([]*tailcfg.SSHPrincipal, 0, len(sshACL.Sources))
|
||||
for innerIndex, rawSrc := range sshACL.Sources {
|
||||
if isWildcard(rawSrc) {
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
"github.com/juanfont/headscale/hscontrol/types"
|
||||
"github.com/juanfont/headscale/hscontrol/util"
|
||||
"github.com/rs/zerolog/log"
|
||||
|
@ -3340,7 +3341,11 @@ func TestSSHRules(t *testing.T) {
|
|||
SSHUsers: map[string]string{
|
||||
"autogroup:nonroot": "=",
|
||||
},
|
||||
Action: &tailcfg.SSHAction{Accept: true, AllowLocalPortForwarding: true},
|
||||
Action: &tailcfg.SSHAction{
|
||||
Accept: true,
|
||||
AllowLocalPortForwarding: true,
|
||||
Recorders: []netip.AddrPort{},
|
||||
},
|
||||
},
|
||||
{
|
||||
SSHUsers: map[string]string{
|
||||
|
@ -3351,7 +3356,11 @@ func TestSSHRules(t *testing.T) {
|
|||
Any: true,
|
||||
},
|
||||
},
|
||||
Action: &tailcfg.SSHAction{Accept: true, AllowLocalPortForwarding: true},
|
||||
Action: &tailcfg.SSHAction{
|
||||
Accept: true,
|
||||
AllowLocalPortForwarding: true,
|
||||
Recorders: []netip.AddrPort{},
|
||||
},
|
||||
},
|
||||
{
|
||||
Principals: []*tailcfg.SSHPrincipal{
|
||||
|
@ -3362,7 +3371,11 @@ func TestSSHRules(t *testing.T) {
|
|||
SSHUsers: map[string]string{
|
||||
"autogroup:nonroot": "=",
|
||||
},
|
||||
Action: &tailcfg.SSHAction{Accept: true, AllowLocalPortForwarding: true},
|
||||
Action: &tailcfg.SSHAction{
|
||||
Accept: true,
|
||||
AllowLocalPortForwarding: true,
|
||||
Recorders: []netip.AddrPort{},
|
||||
},
|
||||
},
|
||||
{
|
||||
SSHUsers: map[string]string{
|
||||
|
@ -3373,7 +3386,100 @@ func TestSSHRules(t *testing.T) {
|
|||
Any: true,
|
||||
},
|
||||
},
|
||||
Action: &tailcfg.SSHAction{Accept: true, AllowLocalPortForwarding: true},
|
||||
Action: &tailcfg.SSHAction{
|
||||
Accept: true,
|
||||
AllowLocalPortForwarding: true,
|
||||
Recorders: []netip.AddrPort{},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ssh-session-recording",
|
||||
node: types.Node{
|
||||
Hostname: "testnodes",
|
||||
IPAddresses: types.NodeAddresses{netip.MustParseAddr("100.64.99.42")},
|
||||
UserID: 0,
|
||||
User: types.User{
|
||||
Name: "user1",
|
||||
},
|
||||
},
|
||||
peers: types.Nodes{
|
||||
&types.Node{
|
||||
Hostname: "testnodes2",
|
||||
IPAddresses: types.NodeAddresses{netip.MustParseAddr("100.64.0.1")},
|
||||
UserID: 0,
|
||||
User: types.User{
|
||||
Name: "user1",
|
||||
},
|
||||
},
|
||||
},
|
||||
pol: ACLPolicy{
|
||||
Groups: Groups{
|
||||
"group:test": []string{"user1"},
|
||||
},
|
||||
Hosts: Hosts{
|
||||
"client": netip.PrefixFrom(netip.MustParseAddr("100.64.99.42"), 32),
|
||||
},
|
||||
ACLs: []ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"*"},
|
||||
Destinations: []string{"*:*"},
|
||||
},
|
||||
},
|
||||
SSHs: []SSH{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"group:test"},
|
||||
Destinations: []string{"client"},
|
||||
Users: []string{"autogroup:nonroot"},
|
||||
Recorder: []string{"group:test"},
|
||||
},
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"*"},
|
||||
Destinations: []string{"client"},
|
||||
Users: []string{"autogroup:nonroot"},
|
||||
Recorder: []string{"client"},
|
||||
EnforceRecorder: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
want: []*tailcfg.SSHRule{
|
||||
{
|
||||
Principals: []*tailcfg.SSHPrincipal{
|
||||
{
|
||||
UserLogin: "user1",
|
||||
},
|
||||
},
|
||||
SSHUsers: map[string]string{
|
||||
"autogroup:nonroot": "=",
|
||||
},
|
||||
Action: &tailcfg.SSHAction{
|
||||
Accept: true,
|
||||
AllowLocalPortForwarding: true,
|
||||
Recorders: []netip.AddrPort{netip.MustParseAddrPort("100.64.0.1:80"), netip.MustParseAddrPort("100.64.99.42:80")},
|
||||
},
|
||||
},
|
||||
{
|
||||
SSHUsers: map[string]string{
|
||||
"autogroup:nonroot": "=",
|
||||
},
|
||||
Principals: []*tailcfg.SSHPrincipal{
|
||||
{
|
||||
Any: true,
|
||||
},
|
||||
},
|
||||
Action: &tailcfg.SSHAction{
|
||||
Accept: true,
|
||||
AllowLocalPortForwarding: true,
|
||||
Recorders: []netip.AddrPort{netip.MustParseAddrPort("100.64.99.42:80")},
|
||||
OnRecordingFailure: &tailcfg.SSHRecorderFailureAction{
|
||||
RejectSessionWithMessage: "# Failed to start session recording.",
|
||||
TerminateSessionWithMessage: "# Failed to start session recording.",
|
||||
},
|
||||
},
|
||||
},
|
||||
}},
|
||||
},
|
||||
|
@ -3435,7 +3541,7 @@ func TestSSHRules(t *testing.T) {
|
|||
got, err := tt.pol.CompileSSHPolicy(&tt.node, tt.peers)
|
||||
assert.NoError(t, err)
|
||||
|
||||
if diff := cmp.Diff(tt.want, got); diff != "" {
|
||||
if diff := cmp.Diff(tt.want, got, cmpopts.EquateComparable(netip.AddrPort{})); diff != "" {
|
||||
t.Errorf("TestSSHRules() unexpected result (-want +got):\n%s", diff)
|
||||
}
|
||||
})
|
||||
|
|
|
@ -53,11 +53,13 @@ type AutoApprovers struct {
|
|||
|
||||
// SSH controls who can ssh into which machines.
|
||||
type SSH struct {
|
||||
Action string `json:"action" yaml:"action"`
|
||||
Sources []string `json:"src" yaml:"src"`
|
||||
Destinations []string `json:"dst" yaml:"dst"`
|
||||
Users []string `json:"users" yaml:"users"`
|
||||
CheckPeriod string `json:"checkPeriod,omitempty" yaml:"checkPeriod,omitempty"`
|
||||
Action string `json:"action" yaml:"action"`
|
||||
Sources []string `json:"src" yaml:"src"`
|
||||
Destinations []string `json:"dst" yaml:"dst"`
|
||||
Users []string `json:"users" yaml:"users"`
|
||||
CheckPeriod string `json:"checkPeriod,omitempty" yaml:"checkPeriod,omitempty"`
|
||||
Recorder []string `json:"recorder,omitempty" yaml:"recorder,omitempty"`
|
||||
EnforceRecorder bool `json:"enforceRecorder,omitempty" yaml:"enforceRecorder,omitempty"`
|
||||
}
|
||||
|
||||
// UnmarshalJSON allows to parse the Hosts directly into netip objects.
|
||||
|
|
Loading…
Reference in New Issue