commit 2502ef306f0898a901a455db64a020655942c8ac Author: rui.zheng Date: Fri Mar 20 17:53:15 2015 +0800 first commit diff --git a/gost.go b/gost.go new file mode 100644 index 0000000..2bb2641 --- /dev/null +++ b/gost.go @@ -0,0 +1,117 @@ +package main + +import ( + //"bufio" + //"bytes" + //"crypto/tls" + //"errors" + "io" + //"io/ioutil" + "log" + "net" + //"net/http" + //"strconv" + //"strings" + //"sync/atomic" + "time" +) + +const ( + readWait = 300 * time.Second + writeWait = 300 * time.Second +) + +type Gost struct { + Laddr, Saddr, Proxy string +} + +func (g *Gost) Run() error { + addr, err := net.ResolveTCPAddr("tcp", g.Laddr) + if err != nil { + return err + } + + ln, err := net.ListenTCP("tcp", addr) + if err != nil { + return err + } + + for { + conn, err := ln.AcceptTCP() + if err != nil { + log.Println("accept:", err) + continue + } + go g.serve(conn) + } + + return ln.Close() +} + +func (g *Gost) serve(conn net.Conn) error { + var pconn net.Conn + defer conn.Close() + + paddr, err := net.ResolveTCPAddr("tcp", g.Proxy) + if err != nil { + log.Println(err) + } + if paddr != nil { + pconn, err = net.DialTCP("tcp", nil, paddr) + if err != nil { + return err + } + return g.foward(conn, pconn) + } + + saddr, err := net.ResolveTCPAddr("tcp", g.Saddr) + if err != nil { + log.Println(err) + } + if saddr != nil { + sconn, err := net.DialTCP("tcp", nil, saddr) + if err != nil { + return err + } + defer sconn.Close() + + return g.transport(conn, sconn) + } + + return nil +} + +func (g *Gost) foward(conn, pconn net.Conn) error { + defer pconn.Close() + + saddr, err := net.ResolveTCPAddr("tcp", g.Saddr) + if err != nil { + log.Println(err) + } + + if saddr != nil { + + } + + return nil +} + +func (g *Gost) pipe(src io.Reader, dst io.Writer, c chan<- error) { + _, err := io.Copy(dst, src) + c <- err +} + +func (g *Gost) transport(conn net.Conn, conn2 net.Conn) (err error) { + rChan := make(chan error, 1) + wChan := make(chan error, 1) + + go g.pipe(conn, conn2, wChan) + go g.pipe(conn2, conn, rChan) + + select { + case err = <-wChan: + case err = <-rChan: + } + + return +} diff --git a/gost2 b/gost2 new file mode 100755 index 0000000..7b17d2d Binary files /dev/null and b/gost2 differ diff --git a/main.go b/main.go new file mode 100644 index 0000000..a68e6c5 --- /dev/null +++ b/main.go @@ -0,0 +1,22 @@ +// main +package main + +import ( + "flag" + "log" +) + +var gost Gost + +func init() { + flag.StringVar(&gost.Proxy, "P", "", "proxy for forward") + flag.StringVar(&gost.Saddr, "S", "", "the server that connecting to") + flag.StringVar(&gost.Laddr, "L", ":8080", "listen address") + flag.Parse() + + log.SetFlags(log.LstdFlags | log.Lshortfile) +} + +func main() { + log.Fatal(gost.Run()) +} diff --git a/socks5.go b/socks5.go new file mode 100644 index 0000000..646cea7 --- /dev/null +++ b/socks5.go @@ -0,0 +1,167 @@ +package main + +import ( + "encoding/binary" + "errors" + "io" + "net" +) + +const ( + Ver5 = 5 +) + +const ( + MethodNoAuth uint8 = iota + MethodGSSAPI + MethodUserPass + // X'03' to X'7F' IANA ASSIGNED + // X'80' to X'FE' RESERVED FOR PRIVATE METHODS + MethodNoAcceptable = 0xFF +) + +const ( + CmdConnect uint8 = 1 + CmdBind = 2 + CmdUdp = 3 +) + +const ( + AddrIPv4 uint8 = 1 + AddrDomain = 3 + AddrIPv6 = 4 +) + +const ( + Succeeded uint8 = iota + Failure + NotAllowed + NetUnreachable + HostUnreachable + ConnRefused + TTLExpired + CmdUnsupported + AddrUnsupported +) + +var ( + ErrBadVersion = errors.New("Bad version") + ErrBadFormat = errors.New("Bad format") + ErrBadAddrType = errors.New("Bad address type") + ErrShortBuffer = errors.New("Short buffer") + + cmdErrMap = map[uint8]error{ + Failure: errors.New("General SOCKS server failure"), + NotAllowed: errors.New("Connection not allowed by ruleset"), + NetUnreachable: errors.New("Network unreachable"), + HostUnreachable: errors.New("Host unreachable"), + ConnRefused: errors.New("Connection refused"), + TTLExpired: errors.New("TTL expired"), + CmdUnsupported: errors.New("Command not supported"), + AddrUnsupported: errors.New("Address type not supported"), + } +) + +/* ++----+-----+-------+------+----------+----------+ +|VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT | ++----+-----+-------+------+----------+----------+ +| 1 | 1 | X'00' | 1 | Variable | 2 | ++----+-----+-------+------+----------+----------+ +*/ +type Cmd struct { + Cmd uint8 + AddrType uint8 + Addr string + Port uint16 +} + +func NewCmd(cmd uint8, atype uint8, addr string, port uint16) *Cmd { + return &Cmd{ + Cmd: cmd, + AddrType: atype, + Addr: addr, + Port: port, + } +} + +func ReadCmd(r io.Reader) (*Cmd, error) { + b := make([]byte, 256) + n, err := r.Read(b) + if err != nil { + return nil, err + } + if n < 10 { + return nil, ErrBadFormat + } + if b[0] != Ver5 { + return nil, ErrBadVersion + } + + cmd := &Cmd{ + Cmd: b[1], + AddrType: b[3], + } + + pos := 4 + + switch cmd.AddrType { + case AddrIPv4: + if n != 10 { + return nil, ErrBadFormat + } + cmd.Addr = net.IP(b[pos : pos+4]).String() + pos += 4 + case AddrIPv6: + if n != 22 { + return nil, ErrBadFormat + } + cmd.Addr = net.IP(b[pos : pos+16]).String() + pos += 16 + case AddrDomain: + length := int(b[pos]) + if n != 4+1+length+2 { + return nil, ErrBadFormat + } + + pos++ + cmd.Addr = string(b[pos : pos+length]) + pos += length + default: + return nil, ErrBadAddrType + } + + cmd.Port = binary.BigEndian.Uint16(b[pos:]) + + return cmd, nil +} + +func (cmd *Cmd) Write(w io.Writer) (err error) { + b := make([]byte, 256) + + b[0] = Ver5 + b[1] = cmd.Cmd + b[3] = cmd.AddrType + pos := 4 + + switch cmd.AddrType { + case AddrIPv4: + pos += copy(b[pos:], net.ParseIP(cmd.Addr).To4()) + case AddrDomain: + b[pos] = byte(len(cmd.Addr)) + pos++ + pos += copy(b[pos:], []byte(cmd.Addr)) + case AddrIPv6: + pos += copy(b[pos:], net.ParseIP(cmd.Addr).To16()) + } + binary.BigEndian.PutUint16(b[pos:], cmd.Port) + pos += 2 + + _, err = w.Write(b[:pos]) + + return +} + +func (cmd *Cmd) GetError() error { + return cmdErrMap[cmd.Cmd] +}