work-in-progress unit tests for socks proxy chain

pull/19/head
David Stainton 9 years ago
parent f87ac5639e
commit 50a9633db0

@ -4,11 +4,14 @@ import (
"bufio" "bufio"
"bytes" "bytes"
"fmt" "fmt"
"golang.org/x/net/proxy" "io"
"net" "net"
"strings" "strings"
"sync" "sync"
"testing" "testing"
"github.com/subgraph/fw-daemon/socks5"
"golang.org/x/net/proxy"
) )
type AccumulatingService struct { type AccumulatingService struct {
@ -17,6 +20,7 @@ type AccumulatingService struct {
mortalService *MortalService mortalService *MortalService
hasProtocolInfo bool hasProtocolInfo bool
hasAuthenticate bool hasAuthenticate bool
receivedChan chan bool
} }
func NewAccumulatingService(net, address string) *AccumulatingService { func NewAccumulatingService(net, address string) *AccumulatingService {
@ -39,53 +43,132 @@ func (a *AccumulatingService) Stop() {
a.mortalService.Stop() a.mortalService.Stop()
} }
func (a *AccumulatingService) WaitUntilReceived() {
<-a.receivedChan
}
func (a *AccumulatingService) SessionWorker(conn net.Conn) error { func (a *AccumulatingService) SessionWorker(conn net.Conn) error {
connReader := bufio.NewReader(conn) connReader := bufio.NewReader(conn)
for { for {
line, err := connReader.ReadBytes('\n') line, err := connReader.ReadBytes('\n')
if err != nil { if err != nil {
fmt.Println("AccumulatingService read error:", err) panic(fmt.Sprintf("AccumulatingService read error: %s", err))
} }
lineStr := strings.TrimSpace(string(line)) lineStr := strings.TrimSpace(string(line))
a.buffer.WriteString(lineStr + "\n") a.buffer.WriteString(lineStr + "\n")
a.receivedChan <- true
}
return nil
}
func fakeSocksSessionWorker(clientConn net.Conn, targetNet, targetAddr string) error {
defer clientConn.Close()
clientAddr := clientConn.RemoteAddr()
fmt.Printf("INFO/socks: New connection from: %v\n", clientAddr)
// Do the SOCKS handshake with the client, and read the command.
fmt.Println("meow1")
req, err := socks5.Handshake(clientConn)
if err != nil {
panic(fmt.Sprintf("ERR/socks: Failed SOCKS5 handshake: %v", err))
}
var upstreamConn net.Conn
upstreamConn, err = net.Dial(targetNet, targetAddr)
if err != nil {
panic(err)
}
fmt.Println("meow2")
defer upstreamConn.Close()
req.Reply(socks5.ReplySucceeded)
fmt.Println("meow3")
// A upstream connection has been established, push data back and forth
// till the session is done.
var wg sync.WaitGroup
wg.Add(2)
//upstreamConn.Write([]byte("meow 123\r\n"))
fmt.Println("meow4")
copyLoop := func(dst, src net.Conn) {
defer wg.Done()
defer dst.Close()
io.Copy(dst, src)
} }
go copyLoop(upstreamConn, clientConn)
go copyLoop(clientConn, upstreamConn)
fmt.Println("meow5")
wg.Wait()
fmt.Printf("INFO/socks: Closed SOCKS connection from: %v\n", clientAddr)
return nil return nil
} }
func TestSocksServerProxyChain(t *testing.T) { func TestSocksServerProxyChain(t *testing.T) {
// socks client ---> socks chain ---> socks server ---> service
socksChainNet := "tcp"
socksChainAddr := "127.0.0.1:7750"
socksServerNet := "tcp"
socksServerAddr := "127.0.0.1:8850"
serviceNet := "tcp"
serviceAddr := "127.0.0.1:9950"
fmt.Println("foo1")
// setup the service listener
service := NewAccumulatingService(serviceNet, serviceAddr)
service.Start()
defer service.Stop()
fmt.Println("foo2")
// setup the "socks server"
session := func(clientConn net.Conn) error {
return fakeSocksSessionWorker(clientConn, serviceNet, serviceAddr)
}
socksService := NewMortalService(socksServerNet, socksServerAddr, session)
socksService.Start()
defer socksService.Stop()
fmt.Println("foo3")
// setup the SOCKS proxy chain
socksConfig := SocksChainConfig{ socksConfig := SocksChainConfig{
TargetSocksNet: "tcp", TargetSocksNet: socksServerNet,
TargetSocksAddr: "127.0.0.1:9050", TargetSocksAddr: socksServerAddr,
ListenSocksNet: "tcp", ListenSocksNet: socksChainNet,
ListenSocksAddr: "127.0.0.1:8850", ListenSocksAddr: socksChainAddr,
} }
wg := sync.WaitGroup{} wg := sync.WaitGroup{}
InitSocksListener(&socksConfig, &wg) InitSocksListener(&socksConfig, &wg)
fmt.Println("foo4")
// setup the SOCKS client
auth := proxy.Auth{ auth := proxy.Auth{
User: "", User: "",
Password: "", Password: "",
} }
forward := proxy.NewPerHost(proxy.Direct, proxy.Direct) forward := proxy.NewPerHost(proxy.Direct, proxy.Direct)
socksClient, err := proxy.SOCKS5(socksChainNet, socksChainAddr, &auth, forward)
terminatingService := NewAccumulatingService("tcp", "127.0.0.1:1234") conn, err := socksClient.Dial(serviceNet, serviceAddr)
terminatingService.Start()
socksClient, err := proxy.SOCKS5("tcp", "127.0.0.1:8850", &auth, forward)
conn, err := socksClient.Dial("tcp", "127.0.0.1:1234")
if err != nil { if err != nil {
panic(err) panic(err)
} }
rd := bufio.NewReader(conn) fmt.Println("foo5")
line := []byte{} conn.Write([]byte("meow 123\r\n"))
line, err = rd.ReadBytes('\n') service.WaitUntilReceived()
if err != nil { fmt.Println("DATA RECEIVED", service.buffer.String())
panic(err) fmt.Println("foo6")
} // read a banner from the service
fmt.Println("socks client received", string(line)) //rd := bufio.NewReader(conn)
//line := []byte{}
//line, err = rd.ReadBytes('\n')
//if err != nil {
// panic(err)
//}
//fmt.Println("socks client received", string(line))
wg.Wait() //wg.Wait()
} }

Loading…
Cancel
Save