Skip to content

Instantly share code, notes, and snippets.

@kingluo
Last active August 29, 2015 14:24
Show Gist options
  • Save kingluo/154017ac186005076485 to your computer and use it in GitHub Desktop.
Save kingluo/154017ac186005076485 to your computer and use it in GitHub Desktop.
go socks5
package pipe
import (
"fmt"
"net"
)
func ConnPipe(c1 net.Conn, c2 net.Conn) {
defer c1.Close()
defer c2.Close()
buf := make([]byte, 4096)
for {
len, err := c1.Read(buf)
if err != nil {
fmt.Println("pipe read", c1, ": ", err.Error())
return
}
len2, err2 := c2.Write(buf[:len])
if err2 != nil || len2 != len {
fmt.Println("pipe write", c2, ": ", err2.Error())
return
}
}
}
import (
"flag"
"fmt"
"net"
"os"
"runtime"
"socks5/utils/mock"
"socks5/utils/pipe"
"strconv"
)
func do_socks5(conn net.Conn) {
buf := make([]byte, 512)
len, err := conn.Read(buf)
if err != nil {
fmt.Println("conn read ", conn, ": ", err.Error())
conn.Close()
return
}
if 1+1+int(buf[1]) != len || int8(buf[0]) != '\x05' {
fmt.Println("invalid proto debug", int(buf[0]))
conn.Close()
return
}
conn.Write([]byte("\x05\x00"))
len, err = conn.Read(buf)
if err != nil {
fmt.Println("conn read ", conn, ": ", err.Error())
conn.Close()
return
}
if len <= 4 {
fmt.Println("invalid proto")
conn.Close()
return
}
ver := int8(buf[0])
cmd := int8(buf[1])
atyp := int8(buf[3])
if ver != '\x05' {
fmt.Println("invalid proto")
conn.Close()
return
}
if cmd != 1 {
fmt.Println("Command not supported")
conn.Write([]byte("\x05\x07\x00\x01\x00\x00\x00\x00\x00\x00"))
conn.Close()
return
}
var dst_addr string
var dst_port uint16
switch atyp {
case 1:
if len != 10 {
fmt.Println("invalid proto")
conn.Close()
return
}
dst_addr = net.IPv4(buf[4], buf[5], buf[6], buf[7]).String()
dst_port = uint16(buf[8])<<8 + uint16(buf[9])
case 3:
addrlen := int(buf[4])
offset := 4 + 1 + addrlen
if offset+2 != len {
fmt.Println("invalid proto")
conn.Close()
return
}
dst_addr = string(buf[5:offset])
dst_port = uint16(buf[offset])<<8 + uint16(buf[offset+1])
default:
fmt.Println("Address type not supported", atyp)
conn.Write([]byte("\x05\x08\x00\x01\x00\x00\x00\x00\x00\x00"))
conn.Close()
return
}
upAddr := dst_addr + ":" + strconv.Itoa(int(dst_port))
fmt.Println(conn, upAddr)
upConn, err := net.Dial("tcp", upAddr)
if err != nil {
fmt.Println("Upstream connect failed, ", upAddr)
conn.Write([]byte("\x05\x01\x00\x01\x00\x00\x00\x00\x00\x00"))
conn.Close()
return
}
conn.Write([]byte("\x05\x00\x00\x01\x00\x00\x00\x00\x00\x00"))
go pipe.ConnPipe(upConn, conn)
pipe.ConnPipe(conn, upConn)
}
func main() {
portPtr := flag.String("port", "12345", "listen port")
wrapPtr := flag.Bool("wrap", false, "wrap toogle")
cookie := flag.Int("cookie", 188, "cookie byte")
flag.Parse()
runtime.GOMAXPROCS(runtime.NumCPU())
ssock, err := net.Listen("tcp", ":"+*portPtr)
if err != nil {
fmt.Println("listen", err.Error())
os.Exit(1)
}
for {
conn, err := ssock.Accept()
if err != nil {
fmt.Println("accept", err.Error())
os.Exit(1)
}
if *wrapPtr {
mock.SetCookie(byte(*cookie))
go do_socks5(mock.Wrap(conn))
} else {
go do_socks5(conn)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment