Browse Source

add tls

1.x
rui.zheng 11 years ago
parent
commit
c462a4df9d
  1. 18
      cert.pem
  2. 33
      client.go
  3. 27
      key.pem
  4. 20
      main.go
  5. 43
      server.go
  6. 287
      socks5.go
  7. 28
      util.go

18
cert.pem

@ -0,0 +1,18 @@
-----BEGIN CERTIFICATE-----
MIIC5jCCAdCgAwIBAgIBADALBgkqhkiG9w0BAQUwEjEQMA4GA1UEChMHQWNtZSBD
bzAeFw0xNDAzMTcwNjIwNTFaFw0xNTAzMTcwNjIwNTFaMBIxEDAOBgNVBAoTB0Fj
bWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDccNO1xmd4lWSf
d/0/QS3E93cYIWHw831i/IKxigdRD/XMZonLdEHywW6lOiXazaP8e6CqPGSmnl0x
5k/3dvGCMj2JCVxM6+z7NpL+AiwvXmvkj/TOciCgwqssCwYS2CiVwjfazRjx1ZUJ
VDC5qiyRsfktQ2fVHrpnJGVSRagmiQgwGWBilVG9B8QvRtpQKN/GQGq17oIQm8aK
kOdPt93g93ojMIg7YJpgDgOirvVz/hDn7YD4ryrtPos9CMafFkJprymKpRHyvz7P
8a3+OkuPjFjPnwOHQ5u1U3+8vC44vfb1ExWzDLoT8Xp8Gndx39k0f7MVOol3GnYu
MN/dvNUdAgMBAAGjSzBJMA4GA1UdDwEB/wQEAwIAoDATBgNVHSUEDDAKBggrBgEF
BQcDATAMBgNVHRMBAf8EAjAAMBQGA1UdEQQNMAuCCWxvY2FsaG9zdDALBgkqhkiG
9w0BAQUDggEBAIG8CJqvTIgJnNOK+i5/IUc/3yF/mSCWuG8qP+Fmo2t6T0PVOtc0
8wiWH5iWtCAhjn0MRY9l/hIjWm6gUZGHCGuEgsOPpJDYGoNLjH9Xwokm4y3LFNRK
UBrrrDbKRNibApBHCapPf6gC5sXcjOwx7P2/kiHDgY7YH47jfcRhtAPNsM4gjsEO
RmwENY+hRUFHIRfQTyalqND+x6PWhRo3K6hpHs4DQEYPq4P2kFPqUqSBymH+Ny5/
BcQ3wdMNmC6Bm/oiL1QV0M+/InOsAgQk/EDd0kmoU1ZT2lYHQduGmP099bOlHNpS
uqO3vXF3q8SPPr/A9TqSs7BKkBQbe0+cdsA=
-----END CERTIFICATE-----

33
client.go

@ -3,6 +3,7 @@ package main
import (
"bufio"
"bytes"
"crypto/tls"
"encoding/binary"
"fmt"
"github.com/ginuerzh/gosocks5"
@ -45,7 +46,7 @@ func handshake(conn net.Conn, methods ...uint8) (method uint8, err error) {
nm = 1
}
b := make([]byte, 2+nm)
b[0] = Ver5
b[0] = gosocks5.Ver5
b[1] = uint8(nm)
copy(b[2:], methods)
@ -57,7 +58,7 @@ func handshake(conn net.Conn, methods ...uint8) (method uint8, err error) {
return
}
if b[0] != Ver5 {
if b[0] != gosocks5.Ver5 {
err = gosocks5.ErrBadVersion
}
method = b[1]
@ -74,17 +75,31 @@ func cliHandle(conn net.Conn) {
}
defer sconn.Close()
method, err := handshake(sconn, MethodAES256, gosocks5.MethodNoAuth)
if err != nil || method == gosocks5.MethodNoAcceptable {
method := gosocks5.MethodNoAuth
for m, v := range Methods {
if Method == v {
method = m
}
}
method, err = handshake(sconn, method)
if err != nil {
return
}
if method == MethodAES256 {
cipher, _ := shadowsocks.NewCipher(Cipher, Password)
switch method {
case MethodTLS:
sconn = tls.Client(sconn, &tls.Config{InsecureSkipVerify: true})
case MethodAES128, MethodAES192, MethodAES256,
MethodDES, MethodBF, MethodCAST5, MethodRC4MD5, MethodRC4, MethodTable:
cipher, _ := shadowsocks.NewCipher(Methods[method], Password)
sconn = shadowsocks.NewConn(sconn, cipher)
case gosocks5.MethodNoAcceptable:
return
}
if Shadows {
cipher, _ := shadowsocks.NewCipher(Cipher, Password)
cipher, _ := shadowsocks.NewCipher(SMethod, SPassword)
conn = shadowsocks.NewConn(conn, cipher)
handleShadow(conn, sconn)
return
@ -157,7 +172,7 @@ func handleSocks5(conn net.Conn, sconn net.Conn) {
uconn, err := net.ListenUDP("udp", nil)
if err != nil {
log.Println(err)
gosocks5.NewReply(Failure, nil).Write(conn)
gosocks5.NewReply(gosocks5.Failure, nil).Write(conn)
return
}
defer uconn.Close()
@ -166,7 +181,7 @@ func handleSocks5(conn net.Conn, sconn net.Conn) {
addr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String())
//log.Println("udp:", addr)
rep = gosocks5.NewReply(Succeeded, addr)
rep = gosocks5.NewReply(gosocks5.Succeeded, addr)
if err := rep.Write(conn); err != nil {
log.Println(err)
return

27
key.pem

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA3HDTtcZneJVkn3f9P0EtxPd3GCFh8PN9YvyCsYoHUQ/1zGaJ
y3RB8sFupTol2s2j/Hugqjxkpp5dMeZP93bxgjI9iQlcTOvs+zaS/gIsL15r5I/0
znIgoMKrLAsGEtgolcI32s0Y8dWVCVQwuaoskbH5LUNn1R66ZyRlUkWoJokIMBlg
YpVRvQfEL0baUCjfxkBqte6CEJvGipDnT7fd4Pd6IzCIO2CaYA4Doq71c/4Q5+2A
+K8q7T6LPQjGnxZCaa8piqUR8r8+z/Gt/jpLj4xYz58Dh0ObtVN/vLwuOL329RMV
swy6E/F6fBp3cd/ZNH+zFTqJdxp2LjDf3bzVHQIDAQABAoIBAHal26147nQ+pHwY
jxwers3XDCjWvup7g79lfcqlKi79UiUEA6KYHm7UogMYewt7p4nb2KwH+XycvDiB
aAUf5flXpTs+6IkWauUDiLZi4PlV7uiEexUq5FjirlL0U/6MjbudX4bK4WQ4uxDc
WaV07Kw2iJFOOHLDKT0en9JaX5jtJNc4ZnE9efFoQ5jfypPWtRw65G1rULEg6nvc
GDh+1ce+4foCkpLRC9c24xAwJONZG6x3UqrSS9qfAsb73nWRQrTfUcO3nhoN8VvL
kL9skn1+S06NyUN0KoEtyRBp+RcpXSsBWAo6qZmo/WqhB/gjzWrxVwn20+yJSm35
ZsMc6QECgYEA8GS+Mp9xfB2szWHz6YTOO1Uu4lHM1ccZMwS1G+dL0KO3uGAiPdvp
woVot6v6w88t7onXsLo5pgz7SYug0CpkF3K/MRd1Ar4lH7PK7IBQ6rFr9ppVxDbx
AEWRswUoPbKCr7W6HU8LbQHDavsDlEIwc6+DiwnL4BzlKjb7RpgQEz0CgYEA6sB5
uHvx3Y5FDcGk1n73leQSAcq14l3ZLNpjrs8msoREDil/j5WmuSN58/7PGMiMgHEi
1vLm3H796JmvGr9OBvspOjHyk07ui2/We/j9Hoxm1VWhyi8HkLNDj70HKalTTFMz
RHO4O+0xCva+h9mKZrRMVktXr2jjdFn/0MYIZ2ECgYAIIsC1IeRLWQ3CHbCNlKsO
IwHlMvOFwKk/qsceXKOaOhA7szU1dr3gkXdL0Aw6mEZrrkqYdpUA46uVf54/rU+Z
445I8QxKvXiwK/uQKX+TkdGflPWWIG3jnnch4ejMvb/ihnn4B/bRB6A/fKNQXzUY
lTYUfI5j1VaEKTwz1W2l2QKBgByFCcSp+jZqhGUpc3dDsZyaOr3Q/Mvlju7uEVI5
hIAHpaT60a6GBd1UPAqymEJwivFHzW3D0NxU6VAK68UaHMaoWNfjHY9b9YsnKS2i
kE3XzN56Ks+/avHfdYPO+UHMenw5V28nh+hv5pdoZrlmanQTz3pkaOC8o3WNQZEB
nh/BAoGBAMY5z2f1pmMhrvtPDSlEVjgjELbaInxFaxPLR4Pdyzn83gtIIU14+R8X
2LPs6PPwrNjWnIgrUSVXncIFL3pa45B+Mx1pYCpOAB1+nCZjIBQmpeo4Y0dwA/XH
85EthKPvoszm+OPbyI16OcePV5ocX7lupRYuAo0pek7bomhmHWHz
-----END RSA PRIVATE KEY-----

20
main.go

@ -10,17 +10,22 @@ import (
var (
Laddr, Saddr, Proxy string
Shadows bool
Cipher, Password string
SMethod, SPassword string
Method, Password string
CertFile, KeyFile string
)
func init() {
flag.StringVar(&Proxy, "P", "", "proxy for forward")
flag.StringVar(&Saddr, "S", "", "the server that connecting to")
flag.StringVar(&Laddr, "L", ":8080", "listen address")
flag.StringVar(&Cipher, "cipher", "rc4-md5", "cipher method")
flag.StringVar(&Password, "password", "[email protected]", "cipher password")
flag.StringVar(&Method, "m", "tls", "cipher method")
flag.StringVar(&Password, "p", "[email protected]", "cipher password")
flag.StringVar(&CertFile, "cert", "cert.pem", "cert.pem file for tls")
flag.StringVar(&KeyFile, "key", "key.pem", "key.pem file for tls")
flag.BoolVar(&Shadows, "ss", false, "shadowsocks compatible")
flag.BoolVar(&Debug, "d", false, "debug option")
flag.StringVar(&SMethod, "sm", "rc4-md5", "shadowsocks cipher method")
flag.StringVar(&SPassword, "sp", "[email protected]", "shadowsocks cipher password")
flag.Parse()
log.SetFlags(log.LstdFlags | log.Lshortfile)
@ -30,9 +35,10 @@ func main() {
//log.Fatal(gost.Run())
if len(Saddr) == 0 {
srv := &gosocks5.Server{
Addr: Laddr,
SelectMethod: selectMethod,
Handle: srvHandle,
Addr: Laddr,
SelectMethod: selectMethod,
MethodSelected: methodSelected,
Handle: srvHandle,
}
log.Fatal(srv.ListenAndServe())
return

43
server.go

@ -5,37 +5,46 @@ import (
"github.com/shadowsocks/shadowsocks-go/shadowsocks"
"net"
//"strconv"
"crypto/tls"
"log"
)
const (
MethodAES256 uint8 = 0x88
)
func selectMethod(methods ...uint8) uint8 {
for _, method := range methods {
if method == MethodAES256 {
if _, ok := Methods[method]; ok {
return method
}
}
return gosocks5.MethodNoAuth
}
func srvHandle(conn net.Conn, method uint8) {
defer conn.Close()
if method == gosocks5.MethodNoAcceptable {
return
}
if method == MethodAES256 {
cipher, _ := shadowsocks.NewCipher(Cipher, Password)
func methodSelected(method uint8, conn net.Conn) (net.Conn, error) {
switch method {
case MethodTLS:
cert, err := tls.LoadX509KeyPair(CertFile, KeyFile)
if err != nil {
log.Println(err)
return nil, err
}
conn = tls.Server(conn, &tls.Config{Certificates: []tls.Certificate{cert}})
case MethodAES128, MethodAES192, MethodAES256,
MethodDES, MethodBF, MethodCAST5, MethodRC4MD5, MethodRC4, MethodTable:
cipher, err := shadowsocks.NewCipher(Methods[method], Password)
if err != nil {
return nil, err
}
conn = shadowsocks.NewConn(conn, cipher)
case gosocks5.MethodNoAcceptable:
return nil, gosocks5.ErrBadMethod
}
return conn, nil
}
func srvHandle(conn net.Conn) {
req, err := gosocks5.ReadRequest(conn)
if err != nil {
log.Println(err)
//log.Println(err)
return
}
@ -96,7 +105,7 @@ func srvHandle(conn net.Conn, method uint8) {
uconn, err := net.ListenUDP("udp", nil)
if err != nil {
log.Println(err)
gosocks5.NewReply(Failure, nil).Write(conn)
gosocks5.NewReply(gosocks5.Failure, nil).Write(conn)
return
}
defer uconn.Close()
@ -104,7 +113,7 @@ func srvHandle(conn net.Conn, method uint8) {
addr := ToSocksAddr(uconn.LocalAddr())
addr.Host, _, _ = net.SplitHostPort(conn.LocalAddr().String())
//log.Println("udp:", addr)
rep := gosocks5.NewReply(Succeeded, addr)
rep := gosocks5.NewReply(gosocks5.Succeeded, addr)
if err := rep.Write(conn); err != nil {
log.Println(err)
return

287
socks5.go

@ -1,287 +0,0 @@
package main
import (
"bytes"
"encoding/binary"
"errors"
"fmt"
"io"
//"log"
"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")
)
/*
+----+-----+-------+------+----------+----------+
|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 {
if len(addr) == 0 {
addr = "0.0.0.0"
}
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)
//log.Println(b[:n])
if err != nil {
//log.Println(err)
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+net.IPv4len]).String()
pos += net.IPv4len
case AddrIPv6:
if n != 22 {
return nil, ErrBadFormat
}
cmd.Addr = net.IP(b[pos : pos+net.IPv6len]).String()
pos += net.IPv6len
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:
pos += 4
}
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) String() string {
return fmt.Sprintf("5 %d 0 %d %s %d",
cmd.Cmd, cmd.AddrType, cmd.Addr, cmd.Port)
}
/*
+----+------+------+----------+----------+----------+
|RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA |
+----+------+------+----------+----------+----------+
| 2 | 1 | 1 | Variable | 2 | Variable |
+----+------+------+----------+----------+----------+
*/
type UdpPayload struct {
Rsv uint16
Frag uint8
AddrType uint8
Addr string
Port uint16
Data []byte
}
func NewUdpPayload(rsv uint16, atype uint8, addr string, port uint16, data []byte) *UdpPayload {
if len(addr) == 0 {
addr = "0.0.0.0"
}
return &UdpPayload{
Rsv: rsv,
AddrType: atype,
Addr: addr,
Port: port,
Data: data,
}
}
func ReadUdpPayload(r io.Reader) (*UdpPayload, error) {
buf := make([]byte, 65797)
n, err := io.ReadAtLeast(r, buf, 5)
//log.Println("r", buf[:n])
if err != nil {
return nil, err
}
up := &UdpPayload{
Rsv: binary.BigEndian.Uint16(buf[:2]),
Frag: buf[2],
AddrType: buf[3],
}
dataIndex := 0
switch up.AddrType {
case AddrIPv4:
dataIndex = 10
case AddrIPv6:
dataIndex = 22
case AddrDomain:
dataIndex = 7 + int(buf[4])
default:
return nil, ErrBadAddrType
}
dataLen := int(up.Rsv)
if n < dataIndex+dataLen {
if _, err := io.ReadFull(r, buf[n:dataIndex+dataLen]); err != nil {
return nil, err
}
}
pos := 4
switch up.AddrType {
case AddrIPv4:
up.Addr = net.IP(buf[pos : pos+net.IPv4len]).String()
pos += net.IPv4len
case AddrIPv6:
up.Addr = net.IP(buf[pos : pos+net.IPv6len]).String()
pos += net.IPv6len
case AddrDomain:
length := int(buf[pos])
pos++
up.Addr = string(buf[pos : pos+length])
pos += length
}
up.Port = binary.BigEndian.Uint16(buf[pos:])
//log.Println(up.Addr, up.Port)
if dataLen > 0 {
up.Data = buf[dataIndex : dataIndex+dataLen]
} else {
up.Data = buf[dataIndex:n]
}
return up, nil
}
func (up *UdpPayload) Write(w io.Writer) error {
buffer := &bytes.Buffer{}
b := make([]byte, 2)
binary.BigEndian.PutUint16(b, up.Rsv)
buffer.Write(b)
buffer.WriteByte(up.Frag)
buffer.WriteByte(up.AddrType)
switch up.AddrType {
case AddrIPv4:
buffer.Write(net.ParseIP(up.Addr).To4())
case AddrDomain:
buffer.WriteByte(uint8(len(up.Addr)))
buffer.Write([]byte(up.Addr))
case AddrIPv6:
buffer.Write(net.ParseIP(up.Addr).To16())
}
binary.BigEndian.PutUint16(b, up.Port)
buffer.Write(b)
buffer.Write(up.Data)
_, err := w.Write(buffer.Bytes())
return err
}
func (up *UdpPayload) String() string {
return fmt.Sprintf("%d %d %d %s %d [%d]",
up.Rsv, up.Frag, up.AddrType, up.Addr, up.Port, len(up.Data))
}

28
util.go

@ -13,12 +13,38 @@ import (
"strconv"
)
const (
MethodTLS uint8 = 0x80 + iota
MethodAES128
MethodAES192
MethodAES256
MethodDES
MethodBF
MethodCAST5
MethodRC4MD5
MethodRC4
MethodTable
)
var Methods = map[uint8]string{
MethodTLS: "tls", // 0x80
MethodAES128: "aes-128-cfb", // 0x81
MethodAES192: "aes-192-cfb", // 0x82
MethodAES256: "aes-256-cfb", // 0x83
MethodDES: "des-cfb", // 0x84
MethodBF: "bf-cfb", // 0x85
MethodCAST5: "cast5-cfb", // 0x86
MethodRC4MD5: "rc4-md5", // 8x87
MethodRC4: "rc4", // 0x88
MethodTable: "table", // 0x89
}
func ToSocksAddr(addr net.Addr) *gosocks5.Addr {
host, port, _ := net.SplitHostPort(addr.String())
p, _ := strconv.Atoi(port)
return &gosocks5.Addr{
Type: AddrIPv4,
Type: gosocks5.AddrIPv4,
Host: host,
Port: uint16(p),
}

Loading…
Cancel
Save