ZBLOG

golang 实现shadowsocks的服务端代码

package main

import (

"crypto/rand"
"crypto/sha256"
"encoding/base64"
"flag"
"fmt"
"io"
"log"
"net"
"strconv"
"time"

"github.com/shadowsocks/go-shadowsocks2/core"

)

var password = flag.String(“password”, “”, “password”) var port = flag.Int(“port”, 8388, “server port”)

func main() {

flag.Parse()
if *password == "" {
    log.Fatalln("Error: password cannot be empty")
}

serverAddr := fmt.Sprintf(":%d", *port)
listen, err := net.Listen("tcp", serverAddr)
if err != nil {
    log.Fatalln(err)
}
defer listen.Close()

log.Printf("Server started on port %d with password %s\n", *port, *password)

for {
    conn, err := listen.Accept()
    if err != nil {
        log.Println(err)
        continue
    }
    go handleConn(conn, *password)
}

}

func handleConn(conn net.Conn, password string) {

defer conn.Close()

buf := make([]byte, 2048)
n, err := conn.Read(buf)
if err != nil {
    log.Println(err)
    return
}

req, err := parseRequest(buf[:n])
if err != nil {
    log.Println(err)
    return
}

// Generate a random IV
iv := make([]byte, 16)
_, err = io.ReadFull(rand.Reader, iv)
if err != nil {
    log.Println(err)
    return
}

block, _ := core.PBKDF2([]byte(password), req.Key, 4096, 32, sha256.New)
stream := core.NewStream(block, iv)

// Write response
resp := make([]byte, 0)
resp = append(resp, byte(len(iv)))
resp = append(resp, iv...)
conn.Write(resp)

// Start data transfer
streamConn := core.NewConn(conn, stream)
defer streamConn.Close()

log.Printf("%s <-> %s\n", conn.RemoteAddr().String(), conn.LocalAddr().String())

// Copy traffic until one side closes the connection
go func() {
    defer streamConn.CloseWrite()
    io.Copy(streamConn, conn)
}()
go func() {
    defer streamConn.CloseRead()
    io.Copy(conn, streamConn)
}()

// Wait for connection to close
select {
case <-time.After(time.Hour * 24 * 365):
    // never timeout
}

}

func parseRequest(buf []byte) (*core.Request, error) {

req := &core.Request{}
if len(buf) < 2 {
    return nil, fmt.Errorf("invalid request")
}
req.Version = buf[0]
req.Cmd = buf[1]
switch req.Cmd {
case core.CmdConnect:
    if len(buf) < 4 {
        return nil, fmt.Errorf("invalid request")
    }
    req.AddressType = buf[3]
    var addr []byte
    switch req.AddressType {
    case core.AddrTypeIPv4:
        if len(buf) < 7 {
            return nil, fmt.Errorf("invalid request")
        }
        addr = buf[4:7]
    case core.AddrTypeIPv6:
        if len(buf) < 19 {
            return nil, fmt.Errorf("invalid request")
        }
        addr = buf[4:19]
    case core.AddrTypeDomain:
        l := int(buf[4])
        if len(buf) < 5+l+2 {
            return nil, fmt.Errorf("invalid request")
        }
        addr = buf[5 : 5+l]
        req.Port = strconv.Itoa(int(buf[5+l])<<8 | int(buf[5+l+1]))
    default:
        return nil, fmt.Errorf("unsupported address type")
    }
    req.Address = net.IP(addr).String()
case core.CmdUDPAssociate:
    return nil, fmt.Errorf("unsupported command")
default:
    return nil, fmt.Errorf("unsupported command")
}
if req.Cmd == core.CmdConnect && req.AddressType != core.AddrTypeDomain {
    portBytes := buf[len(buf)-2:]
    req.Port = strconv.Itoa(int(portBytes[0])<<8 | int(portBytes[1]))
}
return req, nil

}

func init() {

log.SetFlags(log.LstdFlags | log.Lshortfile)

}

func getPassword() string {

password := os.Getenv("SS_PASSWORD")
if password == "" {
    password = "mysecretpassword"
}
return password

}

func getPort() int {

portStr := os.Getenv("SS_PORT")
if portStr == "" {
    portStr = "8388"
}
port, err := strconv.Atoi(portStr)
if err != nil {
    panic(err)
}
return port

}

func main() {

password := getPassword()
port := getPort()

serverAddr := fmt.Sprintf(":%d", port)
listen, err := net.Listen("tcp", serverAddr)
if err != nil {
    panic(err)
}
defer listen.Close()

log.Printf("Server started on port %d with password %s\n", port, password)

for {
    conn, err := listen.Accept()
    if err != nil {
        panic(err)
    }
    go handleConn(conn, password)
}

}

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://golang.0voice.com/?id=2103

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?