ZBLOG

golang 实现shadowsocks的服务端代码

package main

import (

  1. "crypto/rand"
  2. "crypto/sha256"
  3. "encoding/base64"
  4. "flag"
  5. "fmt"
  6. "io"
  7. "log"
  8. "net"
  9. "strconv"
  10. "time"
  11. "github.com/shadowsocks/go-shadowsocks2/core"

)

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

func main() {

  1. flag.Parse()
  2. if *password == "" {
  3. log.Fatalln("Error: password cannot be empty")
  4. }
  5. serverAddr := fmt.Sprintf(":%d", *port)
  6. listen, err := net.Listen("tcp", serverAddr)
  7. if err != nil {
  8. log.Fatalln(err)
  9. }
  10. defer listen.Close()
  11. log.Printf("Server started on port %d with password %s\n", *port, *password)
  12. for {
  13. conn, err := listen.Accept()
  14. if err != nil {
  15. log.Println(err)
  16. continue
  17. }
  18. go handleConn(conn, *password)
  19. }

}

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

  1. defer conn.Close()
  2. buf := make([]byte, 2048)
  3. n, err := conn.Read(buf)
  4. if err != nil {
  5. log.Println(err)
  6. return
  7. }
  8. req, err := parseRequest(buf[:n])
  9. if err != nil {
  10. log.Println(err)
  11. return
  12. }
  13. // Generate a random IV
  14. iv := make([]byte, 16)
  15. _, err = io.ReadFull(rand.Reader, iv)
  16. if err != nil {
  17. log.Println(err)
  18. return
  19. }
  20. block, _ := core.PBKDF2([]byte(password), req.Key, 4096, 32, sha256.New)
  21. stream := core.NewStream(block, iv)
  22. // Write response
  23. resp := make([]byte, 0)
  24. resp = append(resp, byte(len(iv)))
  25. resp = append(resp, iv...)
  26. conn.Write(resp)
  27. // Start data transfer
  28. streamConn := core.NewConn(conn, stream)
  29. defer streamConn.Close()
  30. log.Printf("%s <-> %s\n", conn.RemoteAddr().String(), conn.LocalAddr().String())
  31. // Copy traffic until one side closes the connection
  32. go func() {
  33. defer streamConn.CloseWrite()
  34. io.Copy(streamConn, conn)
  35. }()
  36. go func() {
  37. defer streamConn.CloseRead()
  38. io.Copy(conn, streamConn)
  39. }()
  40. // Wait for connection to close
  41. select {
  42. case <-time.After(time.Hour * 24 * 365):
  43. // never timeout
  44. }

}

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

  1. req := &core.Request{}
  2. if len(buf) < 2 {
  3. return nil, fmt.Errorf("invalid request")
  4. }
  5. req.Version = buf[0]
  6. req.Cmd = buf[1]
  7. switch req.Cmd {
  8. case core.CmdConnect:
  9. if len(buf) < 4 {
  10. return nil, fmt.Errorf("invalid request")
  11. }
  12. req.AddressType = buf[3]
  13. var addr []byte
  14. switch req.AddressType {
  15. case core.AddrTypeIPv4:
  16. if len(buf) < 7 {
  17. return nil, fmt.Errorf("invalid request")
  18. }
  19. addr = buf[4:7]
  20. case core.AddrTypeIPv6:
  21. if len(buf) < 19 {
  22. return nil, fmt.Errorf("invalid request")
  23. }
  24. addr = buf[4:19]
  25. case core.AddrTypeDomain:
  26. l := int(buf[4])
  27. if len(buf) < 5+l+2 {
  28. return nil, fmt.Errorf("invalid request")
  29. }
  30. addr = buf[5 : 5+l]
  31. req.Port = strconv.Itoa(int(buf[5+l])<<8 | int(buf[5+l+1]))
  32. default:
  33. return nil, fmt.Errorf("unsupported address type")
  34. }
  35. req.Address = net.IP(addr).String()
  36. case core.CmdUDPAssociate:
  37. return nil, fmt.Errorf("unsupported command")
  38. default:
  39. return nil, fmt.Errorf("unsupported command")
  40. }
  41. if req.Cmd == core.CmdConnect && req.AddressType != core.AddrTypeDomain {
  42. portBytes := buf[len(buf)-2:]
  43. req.Port = strconv.Itoa(int(portBytes[0])<<8 | int(portBytes[1]))
  44. }
  45. return req, nil

}

func init() {

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

}

func getPassword() string {

  1. password := os.Getenv("SS_PASSWORD")
  2. if password == "" {
  3. password = "mysecretpassword"
  4. }
  5. return password

}

func getPort() int {

  1. portStr := os.Getenv("SS_PORT")
  2. if portStr == "" {
  3. portStr = "8388"
  4. }
  5. port, err := strconv.Atoi(portStr)
  6. if err != nil {
  7. panic(err)
  8. }
  9. return port

}

func main() {

  1. password := getPassword()
  2. port := getPort()
  3. serverAddr := fmt.Sprintf(":%d", port)
  4. listen, err := net.Listen("tcp", serverAddr)
  5. if err != nil {
  6. panic(err)
  7. }
  8. defer listen.Close()
  9. log.Printf("Server started on port %d with password %s\n", port, password)
  10. for {
  11. conn, err := listen.Accept()
  12. if err != nil {
  13. panic(err)
  14. }
  15. go handleConn(conn, password)
  16. }

}

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

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

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

联系我们

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

微信号:3007537140

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

关注我们
x

注册

已经有帐号?