Home | History | Annotate | Download | only in proxy
      1 // Copyright 2011 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package proxy
      6 
      7 import (
      8 	"io"
      9 	"net"
     10 	"net/url"
     11 	"strconv"
     12 	"sync"
     13 	"testing"
     14 )
     15 
     16 func TestFromURL(t *testing.T) {
     17 	endSystem, err := net.Listen("tcp", "127.0.0.1:0")
     18 	if err != nil {
     19 		t.Fatalf("net.Listen failed: %v", err)
     20 	}
     21 	defer endSystem.Close()
     22 	gateway, err := net.Listen("tcp", "127.0.0.1:0")
     23 	if err != nil {
     24 		t.Fatalf("net.Listen failed: %v", err)
     25 	}
     26 	defer gateway.Close()
     27 
     28 	var wg sync.WaitGroup
     29 	wg.Add(1)
     30 	go socks5Gateway(t, gateway, endSystem, socks5Domain, &wg)
     31 
     32 	url, err := url.Parse("socks5://user:password@" + gateway.Addr().String())
     33 	if err != nil {
     34 		t.Fatalf("url.Parse failed: %v", err)
     35 	}
     36 	proxy, err := FromURL(url, Direct)
     37 	if err != nil {
     38 		t.Fatalf("FromURL failed: %v", err)
     39 	}
     40 	_, port, err := net.SplitHostPort(endSystem.Addr().String())
     41 	if err != nil {
     42 		t.Fatalf("net.SplitHostPort failed: %v", err)
     43 	}
     44 	if c, err := proxy.Dial("tcp", "localhost:"+port); err != nil {
     45 		t.Fatalf("FromURL.Dial failed: %v", err)
     46 	} else {
     47 		c.Close()
     48 	}
     49 
     50 	wg.Wait()
     51 }
     52 
     53 func TestSOCKS5(t *testing.T) {
     54 	endSystem, err := net.Listen("tcp", "127.0.0.1:0")
     55 	if err != nil {
     56 		t.Fatalf("net.Listen failed: %v", err)
     57 	}
     58 	defer endSystem.Close()
     59 	gateway, err := net.Listen("tcp", "127.0.0.1:0")
     60 	if err != nil {
     61 		t.Fatalf("net.Listen failed: %v", err)
     62 	}
     63 	defer gateway.Close()
     64 
     65 	var wg sync.WaitGroup
     66 	wg.Add(1)
     67 	go socks5Gateway(t, gateway, endSystem, socks5IP4, &wg)
     68 
     69 	proxy, err := SOCKS5("tcp", gateway.Addr().String(), nil, Direct)
     70 	if err != nil {
     71 		t.Fatalf("SOCKS5 failed: %v", err)
     72 	}
     73 	if c, err := proxy.Dial("tcp", endSystem.Addr().String()); err != nil {
     74 		t.Fatalf("SOCKS5.Dial failed: %v", err)
     75 	} else {
     76 		c.Close()
     77 	}
     78 
     79 	wg.Wait()
     80 }
     81 
     82 func socks5Gateway(t *testing.T, gateway, endSystem net.Listener, typ byte, wg *sync.WaitGroup) {
     83 	defer wg.Done()
     84 
     85 	c, err := gateway.Accept()
     86 	if err != nil {
     87 		t.Errorf("net.Listener.Accept failed: %v", err)
     88 		return
     89 	}
     90 	defer c.Close()
     91 
     92 	b := make([]byte, 32)
     93 	var n int
     94 	if typ == socks5Domain {
     95 		n = 4
     96 	} else {
     97 		n = 3
     98 	}
     99 	if _, err := io.ReadFull(c, b[:n]); err != nil {
    100 		t.Errorf("io.ReadFull failed: %v", err)
    101 		return
    102 	}
    103 	if _, err := c.Write([]byte{socks5Version, socks5AuthNone}); err != nil {
    104 		t.Errorf("net.Conn.Write failed: %v", err)
    105 		return
    106 	}
    107 	if typ == socks5Domain {
    108 		n = 16
    109 	} else {
    110 		n = 10
    111 	}
    112 	if _, err := io.ReadFull(c, b[:n]); err != nil {
    113 		t.Errorf("io.ReadFull failed: %v", err)
    114 		return
    115 	}
    116 	if b[0] != socks5Version || b[1] != socks5Connect || b[2] != 0x00 || b[3] != typ {
    117 		t.Errorf("got an unexpected packet: %#02x %#02x %#02x %#02x", b[0], b[1], b[2], b[3])
    118 		return
    119 	}
    120 	if typ == socks5Domain {
    121 		copy(b[:5], []byte{socks5Version, 0x00, 0x00, socks5Domain, 9})
    122 		b = append(b, []byte("localhost")...)
    123 	} else {
    124 		copy(b[:4], []byte{socks5Version, 0x00, 0x00, socks5IP4})
    125 	}
    126 	host, port, err := net.SplitHostPort(endSystem.Addr().String())
    127 	if err != nil {
    128 		t.Errorf("net.SplitHostPort failed: %v", err)
    129 		return
    130 	}
    131 	b = append(b, []byte(net.ParseIP(host).To4())...)
    132 	p, err := strconv.Atoi(port)
    133 	if err != nil {
    134 		t.Errorf("strconv.Atoi failed: %v", err)
    135 		return
    136 	}
    137 	b = append(b, []byte{byte(p >> 8), byte(p)}...)
    138 	if _, err := c.Write(b); err != nil {
    139 		t.Errorf("net.Conn.Write failed: %v", err)
    140 		return
    141 	}
    142 }
    143