Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

zap: change socks handle from client to server. #17

Merged
merged 1 commit into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,19 @@ var (

serverCommand = &cobra.Command{
Use: "server",
Short: "seaMoon server mod",
Short: "SeaMoon server mod",
RunE: Server,
}

proxyCommand = &cobra.Command{
Use: "proxy",
Short: "seaMoon proxy mod",
Short: "SeaMoon proxy mod",
Run: Proxy,
}

versionCommand = &cobra.Command{
Use: "version",
Use: "version",
Short: "SeaMoon version info",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println(consts.Version)
},
Expand Down
4 changes: 4 additions & 0 deletions pkg/network/addr.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ type Addr struct {
Port uint16
}

type ListenConfig struct {
net.ListenConfig
}

func IsIPv4(address string) bool {
return address != "" && address[0] != ':' && address[0] != '['
}
Expand Down
19 changes: 18 additions & 1 deletion pkg/network/buffer.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,24 @@ package network

// fork from go-gost/core

import "sync"
import (
"bufio"
"net"
"sync"
)

type BufferedConn struct {
net.Conn
Br *bufio.Reader
}

func (c *BufferedConn) Read(b []byte) (int, error) {
return c.Br.Read(b)
}

func (c *BufferedConn) Peek(n int) ([]byte, error) {
return c.Br.Peek(n)
}

var (
pools = []struct {
Expand Down
62 changes: 48 additions & 14 deletions pkg/transfer/socks5.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package transfer

import (
"errors"
"bufio"
"log/slog"
"net"
"time"
Expand All @@ -10,20 +10,49 @@ import (
"github.com/DVKunion/SeaMoon/pkg/network"
)

func Socks5Transport(conn net.Conn, req *network.SOCKS5Request) error {
switch req.Cmd {
case network.SOCKS5CmdConnect:
handleConnect(conn, req)
case network.SOCKS5CmdBind:
handleBind()
case network.SOCKS5CmdUDP:
handleUDPOverTCP()
case network.SOCKS5CmdUDPOverTCP:
handleUDPOverTCP()
default:
return errors.New("")
func Socks5Transport(conn net.Conn) error {
br := &network.BufferedConn{Conn: conn, Br: bufio.NewReader(conn)}
b, err := br.Peek(1)

if err != nil || b[0] != network.SOCKS5Version {
slog.Error(consts.CLIENT_PROTOCOL_UNSUPPORT_ERROR, "err", err)
return err
} else {
// select method
_, err := network.ReadMethods(br)
if err != nil {
slog.Error(`[socks5] read methods failed`, "err", err)
return err
}

// TODO AUTH
if err := network.WriteMethod(network.MethodNoAuth, br); err != nil {
if err != nil {
slog.Error(`[socks5] write method failed`, "err", err)
} else {
slog.Error(`[socks5] methods is not acceptable`)
}
return err
}

// read command
request, err := network.ReadSOCKS5Request(br)
if err != nil {
slog.Error(`[socks5] read command failed`, "err", err)
return err
}
switch request.Cmd {
case network.SOCKS5CmdConnect:
handleConnect(br, request)
case network.SOCKS5CmdBind:
slog.Error("not support cmd bind")
//handleBind(conn, request)
case network.SOCKS5CmdUDPOverTCP:
//handleUDP(conn, request)
slog.Error("not support cmd upd")
}
}
return errors.New("")
return nil
}

func handleConnect(conn net.Conn, req *network.SOCKS5Request) {
Expand All @@ -40,6 +69,11 @@ func handleConnect(conn net.Conn, req *network.SOCKS5Request) {
// if utils.Transport get out , then close conn of remote
defer destConn.Close()

if err := network.NewReply(network.SOCKS5RespSucceeded, nil).Write(conn); err != nil {
slog.Error(consts.SOCKS5_CONNECT_WRITE_ERROR, "err", err)
return
}

slog.Info(consts.SOCKS5_CONNECT_ESTAB, "src", conn.RemoteAddr(), "dest", req.Addr)

if err := network.Transport(conn, destConn); err != nil {
Expand Down
9 changes: 9 additions & 0 deletions server/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ type Options struct {
host string // 监听地址
port string // 监听端口
proto tunnel.Type // 监听协议

mtcp bool //
}

type Option func(o *Options) (err error)
Expand Down Expand Up @@ -34,3 +36,10 @@ func WithProto(t string) Option {
return nil
}
}

func WithMTcp(flag bool) Option {
return func(o *Options) (err error) {
o.mtcp = flag
return nil
}
}
49 changes: 17 additions & 32 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,15 @@ import (
"context"
"errors"
"log/slog"
"net"
"net/http"
"strings"
"time"

"github.com/DVKunion/SeaMoon/pkg/consts"
net "github.com/DVKunion/SeaMoon/pkg/network"
"github.com/DVKunion/SeaMoon/server/service"
)

type Server struct {
srv service.Service
opts Options

startAt time.Time
}

func New(opts ...Option) (*Server, error) {
Expand All @@ -40,46 +35,36 @@ func New(opts ...Option) (*Server, error) {
return s, nil
}

// Serve do common serve
func (s *Server) Serve(ctx context.Context) error {
// http server
serverAddr := strings.Join(append([]string{s.opts.host, s.opts.port}), ":")
network := "tcp"

mux := http.NewServeMux()
if net.IsIPv4(s.opts.host) {
network = "tcp4"
}

serverAddr := strings.Join(append([]string{s.opts.host, s.opts.port}), ":")

lc := net.ListenConfig{}
lc.SetMultipathTCP(true)
if s.opts.mtcp {
lc.SetMultipathTCP(true)
}

ln, err := lc.Listen(ctx, "tcp", serverAddr)
ln, err := lc.Listen(ctx, network, serverAddr)

if err != nil {
return err
}

server := &http.Server{
Addr: serverAddr,
Handler: mux,
}
slog.Info("seamoon server start with", "options", s.opts)

s.srv.Handle(mux)
s.startAt = time.Now()
// inject
mux.HandleFunc("/_health", s.health)
var srvOpt []service.Option

slog.Info("seamoon server start with", "options", s.opts)
// http服务
if err := server.Serve(ln); err != nil {
srvOpt = append(srvOpt, service.WithAddr(serverAddr))

if err := s.srv.Serve(ln, srvOpt...); err != nil {
slog.Error("server error", err)
return err
}
return nil
}

func (s *Server) health(w http.ResponseWriter, _ *http.Request) {
w.Header().Set("Content-Type", "text/plain")
w.WriteHeader(http.StatusOK)
_, err := w.Write([]byte("OK\n" + s.startAt.Format("2006-01-02 15:04:05") + "\n" + consts.Version + "-" + consts.Commit))
if err != nil {
slog.Error("server status error", "msg", err)
return
}
}
56 changes: 56 additions & 0 deletions server/service/options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package service

import (
"crypto/tls"
"time"
)

type Options struct {
addr string

tlsConf *tls.Config
keepalive *KeepAliveOpt
buffers *BufferOpt
}

type Option func(o *Options)

type KeepAliveOpt struct {
MinTime time.Duration
MaxTime time.Duration
Timeout time.Duration
HandshakeTimeout time.Duration
MaxConnectionIdle time.Duration

PermitStream bool
}

type BufferOpt struct {
ReadBufferSize int
WriteBufferSize int
EnableCompression bool
}

func WithAddr(addr string) Option {
return func(o *Options) {
o.addr = addr
}
}

func WithTLSConf(t *tls.Config) Option {
return func(o *Options) {
o.tlsConf = t
}
}

func WithKeepAlive(k *KeepAliveOpt) Option {
return func(o *Options) {
o.keepalive = k
}
}

func WithBuffers(b *BufferOpt) Option {
return func(o *Options) {
o.buffers = b
}
}
4 changes: 2 additions & 2 deletions server/service/service.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package service

import (
"net/http"
"net"

"github.com/DVKunion/SeaMoon/pkg/tunnel"
)

type Service interface {
Handle(m *http.ServeMux)
Serve(ln net.Listener, srvOpt ...Option) error
}

var Factory = map[tunnel.Type]Service{}
Expand Down
Loading
Loading