我自己写的一个小程序,介绍见
我的 Blog 。
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;i0 {
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
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;i0 {
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