go语言写的你懂的东东
xtunnel.go 这个程序运行在本地
package main
import "net" import "log" import "container/list" import "io" import "os" import "sync" const bindAddr = "127.0.0.1:1080" const serverAddr = "www.yourvps.com:2011" const bufferSize = 4096 const maxConn = 0x10000 const xor = 0x64 type tunnel struct { id int * list.Element send chan []byte reply io.Writer } type bundle struct { t [maxConn] tunnel * list.List * xsocket sync.Mutex } type xsocket struct { net.Conn * sync.Mutex } func (s xsocket) Read(data []byte) (n int, err os.Error) { n,err = io.ReadFull(s.Conn, data) if n>0 { for i:=0;i<n;i++ { data[i] = data[i]^xor } } return } func (s xsocket) Write(data []byte) (n int, err os.Error) { s.Lock() defer s.Unlock() log.Println("Send",len(data)) for i:=0;i<len(data);i++ { data[i] = data[i]^xor } x := 0 all := len(data) for all>0 { n, err = s.Conn.Write(data) if err != nil { n += x return } if all != n { log.Println("Write only",n,all) } all -= n x += n data = data[n:] } return all,err } func (t *tunnel) processBack(c net.Conn) { c.SetReadTimeout(1e7) var buf [bufferSize]byte for { n,err := c.Read(buf[4:]) if n>0 { t.sendBack(buf[:4+n]) } e, ok := err.(net.Error); if !(ok && e.Timeout()) && err != nil { log.Println(n,err) return } } } func (t *tunnel) sendClose() { buf := [4]byte { byte(t.id>>8), byte(t.id & 0xff), 0, 0, } t.reply.Write(buf[:]) } func (t *tunnel) sendBack(buf []byte) { buf[0] = byte(t.id>>8) buf[1] = byte(t.id & 0xff) length := len(buf) - 4 buf[2] = byte(length >> 8) buf[3] = byte(length & 0xff) t.reply.Write(buf) } func (t *tunnel) process(c net.Conn,b *bundle) { go t.processBack(c) send := t.send for { buf,ok := <-send if !ok { c.Close() return } n,err := c.Write(buf) if err != nil { b.free(t.id) } else if n!=len(buf) { log.Println("Write",n,len(buf)) } } } func (t *tunnel) open(b *bundle, c net.Conn) { t.send = make(chan []byte) t.reply = b.xsocket go t.process(c,b) } func (t *tunnel) close() { close(t.send) } func newBundle(c net.Conn) *bundle { b := new(bundle) b.List = list.New() for i:=0;i<maxConn;i++ { t := &b.t[i] t.id = i t.Element = b.PushBack(t) } b.xsocket = & xsocket { c , new (sync.Mutex) } return b } func (b *bundle) alloc(c net.Conn) *tunnel { b.Lock() defer b.Unlock() f := b.Front() if f == nil { return nil } t := b.Remove(f).(*tunnel) t.Element = nil t.open(b,c) return t } func (b *bundle) free(id int) { b.Lock() defer b.Unlock() t := &b.t[id] if t.Element == nil { t.sendClose() t.Element = b.PushBack(t) t.close() } } func (b *bundle) get(id int) *tunnel { b.Lock() defer b.Unlock() t := &b.t[id] if t.Element != nil { return nil } return t } func servSocks(b *bundle) { a , err := net.ResolveTCPAddr("tcp",bindAddr) if err != nil { log.Fatal(err) } l , err2 := net.ListenTCP("tcp",a) if err2 != nil { log.Fatal(err2) } log.Printf("xtunnelc bind %s",a) for { c , err := l.Accept() if err != nil { log.Fatal(err) } log.Println(c.RemoteAddr()) b.alloc(c) } } func mainServer(c net.Conn) { b := newBundle(c) go servSocks(b) var header [4]byte for { _,err := b.Read(header[:]) if err != nil { log.Fatal(err) } id := int(header[0]) << 8 | int(header[1]) length := int(header[2]) << 8 | int(header[3]) log.Println("Recv",id,length) if length == 0 { b.free(id) } else { t := b.get(id) buf := make([]byte, length) n,err := b.Read(buf) if err != nil { log.Fatal(err) } else if n!=len(buf) { log.Println("Read",n,len(buf)) } if t != nil { t.send <- buf } } } } func start(addr string) { a , err := net.ResolveTCPAddr("tcp",addr) if err != nil { log.Fatal(err) } c,err2 := net.DialTCP("tcp", nil, a) if err2 != nil { log.Fatal(err2) } log.Printf("xtunnelc connect %s",a) mainServer(c) } func main() { start(serverAddr) }
xtunneld.go 这个程序运行在墙外
package main
import "net" import "log" import "container/list" import "io" import "os" import "sync" const socksServer = "127.0.0.1:1080" const bindAddr = ":2011" const bufferSize = 4096 const maxConn = 0x10000 const xor = 0x64 var socksAddr * net.TCPAddr func init() { var err os.Error socksAddr , err = net.ResolveTCPAddr("tcp",socksServer) if err != nil { log.Fatal(err) } } type tunnel struct { id int * list.Element send chan []byte reply io.Writer } type bundle struct { t [maxConn] tunnel * list.List * xsocket } type xsocket struct { net.Conn * sync.Mutex } func (s xsocket) Read(data []byte) (n int, err os.Error) { n,err = io.ReadFull(s.Conn, data) if n>0 { for i:=0;i<n;i++ { data[i] = data[i]^xor } } return } func (s xsocket) Write(data []byte) (n int, err os.Error) { s.Lock() defer s.Unlock() log.Println("Send",len(data)) for i:=0;i<len(data);i++ { data[i] = data[i]^xor } x := 0 all := len(data) for all>0 { n, err = s.Conn.Write(data) if err != nil { n += x return } all -= n x += n data = data[n:] } return all,err } func (t *tunnel) processBack(c net.Conn) { c.SetReadTimeout(1e7) var buf [bufferSize]byte for { n,err := c.Read(buf[4:]) if n>0 { t.sendBack(buf[:4+n]) } e, ok := err.(net.Error) if !(ok && e.Timeout()) && err != nil { log.Println(n,err) return } } } func (t *tunnel) sendClose() { buf := [4]byte { byte(t.id>>8), byte(t.id & 0xff), 0, 0, } t.reply.Write(buf[:]) } func (t *tunnel) sendBack(buf []byte) { buf[0] = byte(t.id>>8) buf[1] = byte(t.id & 0xff) length := len(buf) - 4 buf[2] = byte(length >> 8) buf[3] = byte(length & 0xff) t.reply.Write(buf) } func connectSocks() net.Conn { c,err := net.DialTCP("tcp", nil, socksAddr) if err != nil { return nil } log.Println(c.RemoteAddr()) return c } func (t *tunnel) process() { c := connectSocks() if c==nil { t.sendClose() } else { go t.processBack(c) } send := t.send for { buf,ok := <-send if !ok { if c!=nil { c.Close() } return } if c!=nil { n,err := c.Write(buf) if err != nil { log.Println("tunnel",n,err) t.sendClose() } } } } func (t *tunnel) open(reply io.Writer) { t.send = make(chan []byte) t.reply = reply go t.process() } func (t *tunnel) close() { close(t.send) } func newBundle(c net.Conn) *bundle { b := new(bundle) b.List = list.New() for i:=0;i<maxConn;i++ { t := &b.t[i] t.id = i t.Element = b.PushBack(t) } b.xsocket = & xsocket { c , new(sync.Mutex) } return b } func (b *bundle) free(id int) { t := &b.t[id] if t.Element == nil { t.Element = b.PushBack(t) t.close() } } func (b *bundle) get(id int) *tunnel { t := &b.t[id] if t.Element != nil { b.Remove(t.Element) t.Element = nil t.open(b.xsocket) } return t } func servTunnel(c net.Conn) { b := newBundle(c) var header [4]byte for { _,err := b.Read(header[:]) if err != nil { log.Fatal(err) } id := int(header[0]) << 8 | int(header[1]) length := int(header[2]) << 8 | int(header[3]) log.Println("Recv",id,length) if length == 0 { b.free(id) } else { t := b.get(id) buf := make([]byte, length) _,err := b.Read(buf) if err != nil { log.Fatal(err) } t.send <- buf } } } func start(addr string) { a , err := net.ResolveTCPAddr("tcp",addr) if err != nil { log.Fatal(err) } l , err2 := net.ListenTCP("tcp",a) if err2 != nil { log.Fatal(err2) } log.Printf("xtunneld bind %s",a) c , err3 := l.Accept() if err3 != nil { log.Fatal(err3) } l.Close() servTunnel(c) } func main() { start(bindAddr) }