132 lines
2.6 KiB
Go
132 lines
2.6 KiB
Go
package socket5
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"go-socket5-proxy/helper"
|
|
"io"
|
|
"log"
|
|
"net"
|
|
)
|
|
|
|
type Server interface {
|
|
Run() error
|
|
}
|
|
|
|
type Socket5Server struct {
|
|
Port int64
|
|
IP string
|
|
}
|
|
|
|
func (s *Socket5Server) Run() error {
|
|
address := fmt.Sprintf("%s:%d", s.IP, s.Port)
|
|
fmt.Printf("%s:%d \n", s.IP, s.Port)
|
|
listen, err := helper.CreateListen(address)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
return err
|
|
}
|
|
|
|
for {
|
|
conn, err := listen.Accept()
|
|
if err != nil {
|
|
log.Printf("连接失败:%s: %s", conn.RemoteAddr(), err)
|
|
}
|
|
|
|
go func() {
|
|
defer conn.Close()
|
|
err = handleConnection(conn)
|
|
if err != nil {
|
|
//log.Printf("处理连接 handleConnection %s: %s", conn.RemoteAddr(), err)
|
|
}
|
|
|
|
}()
|
|
|
|
}
|
|
}
|
|
|
|
// 处理连接 handleConnection
|
|
func handleConnection(conn net.Conn) error {
|
|
|
|
//协商过程
|
|
if err := auth(conn); err != nil {
|
|
return err
|
|
}
|
|
|
|
//请求过程
|
|
targetConn, err := request(conn)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if targetConn == nil {
|
|
return nil
|
|
}
|
|
//转发过程
|
|
return forward(conn, targetConn)
|
|
}
|
|
|
|
func forward(conn net.Conn, targetConn net.Conn) error {
|
|
defer targetConn.Close()
|
|
go io.Copy(targetConn, conn)
|
|
_, err := io.Copy(conn, targetConn)
|
|
return err
|
|
}
|
|
|
|
func request(conn net.Conn) (net.Conn, error) {
|
|
message, err := NewClientRequestMessage(conn)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
//检查命令是否支持
|
|
if message.CMD != CmdConnect {
|
|
return nil, WriteRequestFailureMessage(conn, ReplyCommandNotSupported)
|
|
}
|
|
|
|
//ipv6
|
|
if message.AddressType == TypeIPV6 {
|
|
return nil, WriteRequestFailureMessage(conn, ReplyAddressTypeNotSupported)
|
|
}
|
|
|
|
//请求访问目标服务器
|
|
addres := fmt.Sprintf("%s:%d", message.Address, message.Port)
|
|
//fmt.Printf("请求访问目标服务器:%v\n", message.AddressType)
|
|
targetConn, err := net.Dial("tcp", addres)
|
|
if err != nil {
|
|
return nil, WriteRequestFailureMessage(conn, ReplyConnectionRefused)
|
|
}
|
|
|
|
//发送成功
|
|
addrValue := targetConn.LocalAddr()
|
|
addr := addrValue.(*net.TCPAddr)
|
|
|
|
if targetConn == nil {
|
|
fmt.Printf("targetConn is nil :" + addr.IP.String())
|
|
}
|
|
|
|
return targetConn, WriteRequestSuccessMessage(conn, addr.IP, uint16(addr.Port))
|
|
}
|
|
|
|
func auth(conn net.Conn) error {
|
|
client, err := NewClientAuthMessage(conn)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
//log.Println(client.Version, client.NMethods, client.Methods)
|
|
|
|
// 是否支持 no-auth
|
|
var accept_table bool
|
|
for _, method := range client.Methods {
|
|
if method == Method_NO_AUTH {
|
|
accept_table = true
|
|
}
|
|
}
|
|
|
|
if !accept_table {
|
|
NewServerAuthMessage(conn, Method_NO_ACCEPT_TABLE)
|
|
return errors.New("方法不支持 not auth")
|
|
}
|
|
|
|
return NewServerAuthMessage(conn, Method_NO_AUTH)
|
|
}
|