@ -11,11 +11,13 @@ import (
"io"
"net/http"
"net/http/httptest"
"net/netip"
"os"
"path/filepath"
"testing"
"time"
"golang.org/x/net/proxy"
"tailscale.com/ipn/store/mem"
"tailscale.com/net/netns"
"tailscale.com/tailcfg"
@ -99,48 +101,37 @@ func startControl(t *testing.T) (controlURL string) {
return controlURL
}
func TestConn ( t * testing . T ) {
controlURL := startControl ( t )
func startServer ( t * testing . T , ctx context . Context , controlURL , hostname string ) ( * Server , netip . Addr ) {
t. Helper ( )
tmp := t . TempDir ( )
tmps1 := filepath . Join ( tmp , "s1" )
os . MkdirAll ( tmps1 , 0755 )
s1 := & Server {
Dir : tmps1 ,
tmp := filepath . Join ( t . TempDir ( ) , hostname )
os . MkdirAll ( tmp , 0755 )
s := & Server {
Dir : tmp ,
ControlURL : controlURL ,
Hostname : "s1" ,
Hostname : hostname ,
Store : new ( mem . Store ) ,
Ephemeral : true ,
}
defer s1 . Close ( )
tmps2 := filepath . Join ( tmp , "s1" )
os . MkdirAll ( tmps2 , 0755 )
s2 := & Server {
Dir : tmps2 ,
ControlURL : controlURL ,
Hostname : "s2" ,
Store : new ( mem . Store ) ,
Ephemeral : true ,
if ! * verboseNodes {
s . Logf = logger . Discard
}
defer s2 . Close ( )
t . Cleanup ( func ( ) { s . Close ( ) } )
if ! * verboseNodes {
s1 . Logf = logger . Discard
s2. Logf = logger . Discard
status , err := s . Up ( ctx )
if err != nil {
t . Fatal ( err )
}
return s , status . TailscaleIPs [ 0 ]
}
func TestConn ( t * testing . T ) {
ctx , cancel := context . WithTimeout ( context . Background ( ) , 30 * time . Second )
defer cancel ( )
s1status , err := s1 . Up ( ctx )
if err != nil {
t . Fatal ( err )
}
s1ip := s1status . TailscaleIPs [ 0 ]
if _ , err := s2 . Up ( ctx ) ; err != nil {
t . Fatal ( err )
}
controlURL := startControl ( t )
s1 , s1ip := startServer ( t , ctx , controlURL , "s1" )
s2 , _ := startServer ( t , ctx , controlURL , "s2" )
lc2 , err := s2 . LocalClient ( )
if err != nil {
@ -187,31 +178,19 @@ func TestConn(t *testing.T) {
}
func TestLoopbackLocalAPI ( t * testing . T ) {
controlURL := startControl ( t )
tmp := t . TempDir ( )
tmps1 := filepath . Join ( tmp , "s1" )
os . MkdirAll ( tmps1 , 0755 )
s1 := & Server {
Dir : tmps1 ,
ControlURL : controlURL ,
Hostname : "s1" ,
Store : new ( mem . Store ) ,
Ephemeral : true ,
}
defer s1 . Close ( )
ctx , cancel := context . WithTimeout ( context . Background ( ) , 10 * time . Second )
ctx , cancel := context . WithTimeout ( context . Background ( ) , 30 * time . Second )
defer cancel ( )
if _ , err := s1 . Up ( ctx ) ; err != nil {
t . Fatal ( err )
}
controlURL := startControl ( t )
s1 , _ := startServer ( t , ctx , controlURL , "s1" )
addr , cred, err := s1 . Loopback LocalAPI ( )
addr , proxyCred , localAPICred , err := s1 . Loopback ( )
if err != nil {
t . Fatal ( err )
}
if proxyCred == localAPICred {
t . Fatal ( "proxy password matches local API password, they should be different" )
}
url := "http://" + addr + "/localapi/v0/status"
req , err := http . NewRequestWithContext ( ctx , "GET" , url , nil )
@ -245,7 +224,7 @@ func TestLoopbackLocalAPI(t *testing.T) {
if err != nil {
t . Fatal ( err )
}
req . SetBasicAuth ( "" , cred)
req . SetBasicAuth ( "" , lo calAPIC red)
res , err = http . DefaultClient . Do ( req )
if err != nil {
t . Fatal ( err )
@ -260,7 +239,7 @@ func TestLoopbackLocalAPI(t *testing.T) {
t . Fatal ( err )
}
req . Header . Set ( "Sec-Tailscale" , "localapi" )
req . SetBasicAuth ( "" , cred)
req . SetBasicAuth ( "" , lo calAPIC red)
res , err = http . DefaultClient . Do ( req )
if err != nil {
t . Fatal ( err )
@ -270,3 +249,53 @@ func TestLoopbackLocalAPI(t *testing.T) {
t . Errorf ( "GET /status returned %d, want 200" , res . StatusCode )
}
}
func TestLoopbackSOCKS5 ( t * testing . T ) {
ctx , cancel := context . WithTimeout ( context . Background ( ) , 30 * time . Second )
defer cancel ( )
controlURL := startControl ( t )
s1 , s1ip := startServer ( t , ctx , controlURL , "s1" )
s2 , _ := startServer ( t , ctx , controlURL , "s2" )
addr , proxyCred , _ , err := s2 . Loopback ( )
if err != nil {
t . Fatal ( err )
}
ln , err := s1 . Listen ( "tcp" , ":8081" )
if err != nil {
t . Fatal ( err )
}
defer ln . Close ( )
auth := & proxy . Auth { User : "tsnet" , Password : proxyCred }
socksDialer , err := proxy . SOCKS5 ( "tcp" , addr , auth , proxy . Direct )
if err != nil {
t . Fatal ( err )
}
w , err := socksDialer . Dial ( "tcp" , fmt . Sprintf ( "%s:8081" , s1ip ) )
if err != nil {
t . Fatal ( err )
}
r , err := ln . Accept ( )
if err != nil {
t . Fatal ( err )
}
want := "hello"
if _ , err := io . WriteString ( w , want ) ; err != nil {
t . Fatal ( err )
}
got := make ( [ ] byte , len ( want ) )
if _ , err := io . ReadAtLeast ( r , got , len ( got ) ) ; err != nil {
t . Fatal ( err )
}
t . Logf ( "got: %q" , got )
if string ( got ) != want {
t . Errorf ( "got %q, want %q" , got , want )
}
}