mirror of
https://github.com/tailscale/tailscale.git
synced 2025-05-04 06:31:54 +00:00
interfaces, cmd/tsshd: move interface lookup from tsshd to its own package
For reuse by derper, etc. Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
parent
37e115834e
commit
433b917977
@ -25,7 +25,6 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
@ -33,6 +32,7 @@ import (
|
|||||||
"github.com/gliderlabs/ssh"
|
"github.com/gliderlabs/ssh"
|
||||||
"github.com/kr/pty"
|
"github.com/kr/pty"
|
||||||
gossh "golang.org/x/crypto/ssh"
|
gossh "golang.org/x/crypto/ssh"
|
||||||
|
"tailscale.com/interfaces"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -57,7 +57,7 @@ func main() {
|
|||||||
|
|
||||||
warned := false
|
warned := false
|
||||||
for {
|
for {
|
||||||
addr, iface, err := tailscaleInterface()
|
addr, iface, err := interfaces.Tailscale()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("listing interfaces: %v", err)
|
log.Fatalf("listing interfaces: %v", err)
|
||||||
}
|
}
|
||||||
@ -87,50 +87,6 @@ func main() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// tailscaleInterface returns an err on a fatal problem, and all zero values
|
|
||||||
// if no suitable inteface is found.
|
|
||||||
func tailscaleInterface() (net.IP, *net.Interface, error) {
|
|
||||||
ifs, err := net.Interfaces()
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
for _, iface := range ifs {
|
|
||||||
if !maybeTailscaleInterfaceName(iface.Name) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
addrs, err := iface.Addrs()
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, a := range addrs {
|
|
||||||
if ipnet, ok := a.(*net.IPNet); ok && isTailscaleIP(ipnet.IP) {
|
|
||||||
return ipnet.IP, &iface, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// maybeTailscaleInterfaceName reports whether s is an interface
|
|
||||||
// name that might be used by Tailscale.
|
|
||||||
func maybeTailscaleInterfaceName(s string) bool {
|
|
||||||
return strings.HasPrefix(s, "wg") ||
|
|
||||||
strings.HasPrefix(s, "ts") ||
|
|
||||||
strings.HasPrefix(s, "tailscale")
|
|
||||||
}
|
|
||||||
|
|
||||||
func isTailscaleIP(ip net.IP) bool {
|
|
||||||
return cgNAT.Contains(ip)
|
|
||||||
}
|
|
||||||
|
|
||||||
var cgNAT = func() *net.IPNet {
|
|
||||||
_, ipNet, err := net.ParseCIDR("100.64.0.0/10")
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return ipNet
|
|
||||||
}()
|
|
||||||
|
|
||||||
func handleSSH(s ssh.Session) {
|
func handleSSH(s ssh.Session) {
|
||||||
user := s.User()
|
user := s.User()
|
||||||
addr := s.RemoteAddr()
|
addr := s.RemoteAddr()
|
||||||
@ -140,7 +96,7 @@ func handleSSH(s ssh.Session) {
|
|||||||
s.Exit(1)
|
s.Exit(1)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !isTailscaleIP(ta.IP) {
|
if !interfaces.IsTailscaleIP(ta.IP) {
|
||||||
log.Printf("tsshd: rejecting non-Tailscale addr %v", ta.IP)
|
log.Printf("tsshd: rejecting non-Tailscale addr %v", ta.IP)
|
||||||
s.Exit(1)
|
s.Exit(1)
|
||||||
return
|
return
|
||||||
|
58
interfaces/interfaces.go
Normal file
58
interfaces/interfaces.go
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
// Copyright (c) 2020 Tailscale Inc & AUTHORS All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package interfaces contains helpers for looking up system network interfaces.
|
||||||
|
package interfaces
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Tailscale returns the current machine's Tailscale interface, if any.
|
||||||
|
// If none is found, all zero values are returned.
|
||||||
|
// A non-nil error is only returned on a problem listing the system interfaces.
|
||||||
|
func Tailscale() (net.IP, *net.Interface, error) {
|
||||||
|
ifs, err := net.Interfaces()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
for _, iface := range ifs {
|
||||||
|
if !maybeTailscaleInterfaceName(iface.Name) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
addrs, err := iface.Addrs()
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, a := range addrs {
|
||||||
|
if ipnet, ok := a.(*net.IPNet); ok && IsTailscaleIP(ipnet.IP) {
|
||||||
|
return ipnet.IP, &iface, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// maybeTailscaleInterfaceName reports whether s is an interface
|
||||||
|
// name that might be used by Tailscale.
|
||||||
|
func maybeTailscaleInterfaceName(s string) bool {
|
||||||
|
return strings.HasPrefix(s, "wg") ||
|
||||||
|
strings.HasPrefix(s, "ts") ||
|
||||||
|
strings.HasPrefix(s, "tailscale")
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsTailscaleIP reports whether ip is an IP in a range used by
|
||||||
|
// Tailscale virtual network interfaces.
|
||||||
|
func IsTailscaleIP(ip net.IP) bool {
|
||||||
|
return cgNAT.Contains(ip)
|
||||||
|
}
|
||||||
|
|
||||||
|
var cgNAT = func() *net.IPNet {
|
||||||
|
_, ipNet, err := net.ParseCIDR("100.64.0.0/10")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return ipNet
|
||||||
|
}()
|
31
interfaces/interfaces_test.go
Normal file
31
interfaces/interfaces_test.go
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// Copyright (c) 2020 Tailscale Inc & AUTHORS All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package interfaces
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestIsTailscaleIP(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
ip string
|
||||||
|
want bool
|
||||||
|
}{
|
||||||
|
{"100.81.251.94", true},
|
||||||
|
{"8.8.8.8", false},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
ip := net.ParseIP(tt.ip)
|
||||||
|
if ip == nil {
|
||||||
|
t.Fatalf("failed to parse IP %q", tt.ip)
|
||||||
|
}
|
||||||
|
got := IsTailscaleIP(ip)
|
||||||
|
if got != tt.want {
|
||||||
|
t.Errorf("F(%q) = %v; want %v", tt.ip, got, tt.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user