socks5
This is a Golang implementation of the Socks5 protocol library.
To see in this SOCKS Protocol Version 5.
This library is also compatible with Socks4 and Socks4a.
Contents
Features
- socks5:
- command: CONNECT, UDP ASSOCIATE, BIND.
- auth methods:
- Username/Password authentication.
- No Authentication Required.
- socks4:
- command: CONNECT, BIND.
- auth: (no support).
- sock4a: same as socks4.
- Custom client and server authenticator.
- Easy to read source code.
- Similar to the Golang standard library experience.
Installation
$ go get "github.com/haochen233/socks5"`
Examples
Server example
simple (no authentication):
package main
import (
"log"
"github.com/haochen233/socks5"
)
func main() {
srv := &socks5.Server{
Addr: "127.0.0.1:1080",
BindIP: "127.0.0.1",
Authenticators: nil,
}
err := srv.ListenAndServe()
if err != nil {
log.Fatal(err)
}
}
username/password authentication in memory:
package main
import (
"crypto/md5"
"log"
"github.com/haochen233/socks5"
)
func main() {
var userStorage socks5.UserPwdStore = socks5.NewMemeryStore(md5.New(), "secret")
userStorage.Set("admin", "123456")
srv := &socks5.Server{
Addr: "127.0.0.1:1080",
BindIP: "127.0.0.1",
Authenticators: map[socks5.METHOD]socks5.Authenticator{
socks5.USERNAME_PASSWORD: socks5.UserPwdAuth{UserPwdStore: userStorage},
socks5.NO_AUTHENTICATION_REQUIRED: socks5.NoAuth{},
},
}
err := srv.ListenAndServe()
if err != nil {
log.Fatal(err)
}
}
custom transporter to transmit data between client and remote.
package main
import (
"log"
"net"
"github.com/haochen233/socks5"
)
type cryptTransport struct {
}
func (c *cryptTransport) TransportTCP(client *net.TCPConn, remote *net.TCPConn) <-chan error {
return nil
}
func (c *cryptTransport) TransportUDP(server *socks5.UDPConn, request *socks5.Request) error {
panic("implement me")
return nil
}
func main() {
server := &socks5.Server{
Addr: "127.0.0.1:1080",
BindIP: "127.0.0.1",
Transporter: &cryptTransport{},
}
err := server.ListenAndServe()
if err != nil {
log.Fatal(err)
}
}
Client example
CONNECT usage:
package main
import (
"log"
"github.com/haochen233/socks5"
)
func main() {
clnt := socks5.Client{
ProxyAddr: "127.0.0.1:1080",
Auth: map[socks5.METHOD]socks5.Authenticator{
socks5.NO_AUTHENTICATION_REQUIRED: &socks5.NoAuth{},
},
}
conn, err := clnt.Connect(socks5.Version5, "www.baidu.com:80")
if err != nil {
log.Fatal(err)
}
conn.Close()
}
UDP_ASSOCIATE usage:
package main
import (
"fmt"
"log"
"github.com/haochen233/socks5"
)
func main() {
clnt := socks5.Client{
ProxyAddr: "127.0.0.1:1080",
Auth: map[socks5.METHOD]socks5.Authenticator{
socks5.NO_AUTHENTICATION_REQUIRED: &socks5.NoAuth{},
socks5.USERNAME_PASSWORD: &socks5.UserPasswd{Username: "admin", Password: "123456"},
},
}
conn, err := clnt.UDPForward("")
if err != nil {
log.Fatal(err)
}
defer conn.Close()
someData := []byte("some data")
destAddr, _ := socks5.ParseAddress("127.0.0.1:9190")
pakcedData, err := socks5.PackUDPData(destAddr, someData)
conn.Write(pakcedData)
buf := make([]byte, 65507)
conn.Read(buf)
destAddr, unpackedData, err := socks5.UnpackUDPData(buf)
fmt.Println(unpackedData)
}
BIND usage:
package main
import (
"encoding/binary"
"github.com/haochen233/socks5"
"log"
)
func main() {
c := socks5.Client{
ProxyAddr: "172.16.1.28:1080",
Auth: map[socks5.METHOD]socks5.Authenticator{
socks5.USERNAME_PASSWORD: &socks5.UserPasswd{"admin", "123456"},
socks5.NO_AUTHENTICATION_REQUIRED: &socks5.NoAuth{},
},
}
conn1, err := c.Connect(5, "127.0.0.1:9000")
if err != nil {
log.Fatal(err)
}
dest := "127.0.0.1:9001"
bindAddr, errors, conn2, err := c.Bind(4, dest)
if err != nil {
log.Fatal(err)
}
port := make([]byte, 2)
binary.BigEndian.PutUint16(port, bindAddr.Port)
conn1.Write(append(bindAddr.Addr, port...))
err = <-errors
if err != nil {
log.Fatal(err)
return
}
_, err = conn2.Write([]byte("hello"))
if err != nil {
return
log.Fatal(err)
}
}
FAQ: