proxy-service.zip
package main
import (
"fmt"
"io"
"log"
"net"
"os"
// "strconv"
"sync"
)
var localIP = ""
var domainsMap sync.Map
// 域名解析
func DomainResolution(domain string) (string, error) {
if domain, ok := domainsMap.Load(domain); ok {
return domain.(string), nil
}
ips, err := net.LookupIP(domain)
if err != nil {
return "", fmt.Errorf("无法解析域名: %w", err)
}
var addr string
for _, ip := range ips {
if ip.To4() != nil {
addr = ip.String()
break
}
}
domainsMap.Store(domain, addr)
return "", fmt.Errorf("无法解析域名: %w", err)
}
// 如果接口不存在或没有IPv4地址,则返回空字符串。
func Init(interfaceName string) {
interfaces, err := net.Interfaces()
if err != nil {
log.Println("获取网络接口列表失败:", err)
os.Exit(0)
}
for _, iface := range interfaces {
if iface.Name == interfaceName {
addrs, err := iface.Addrs()
if err != nil {
log.Println("获取接口地址失败:", err)
os.Exit(0)
}
for _, addr := range addrs {
// 检查是否为IPv4地址
ipNet, ok := addr.(*net.IPNet)
if ok && ipNet.IP.To4() != nil {
localIP = ipNet.IP.String()
log.Println("获取网卡IP:", localIP)
return
}
}
log.Println("获取网络接口列表失败:", err)
os.Exit(0)
}
}
log.Println("指定网卡%s不存在", interfaceName)
os.Exit(0)
}
// 指定网卡链接
func dialWithSpecificLocalAddr(remoteAddr, localIP string, remotePort int) (net.Conn, error) {
// 创建一个TCP地址用于绑定本地端点
localAddr := net.TCPAddr{
IP: net.ParseIP(localIP),
Port: 0, // 使用0可以让系统自动选择一个可用端口
}
// 连接到远程地址
conn, err := net.DialTCP("tcp", &localAddr, &net.TCPAddr{
IP: net.ParseIP(remoteAddr),
Port: remotePort,
})
if err != nil {
return nil, err
}
return conn, nil
}
// 获取ip,端口
func getTargetIpPort(conn net.Conn) (string, int, error) {
// 读取目标服务器地址
var addr string
atyp, err := readByte(conn)
if err != nil {
return "", 0, fmt.Errorf("读取地址类型失败:", err)
}
switch atyp {
case 0x01: // IPv4
ip := make([]byte, 4)
if _, err := io.ReadFull(conn, ip); err != nil {
err = fmt.Errorf("读取IPv4地址失败:", err)
}
addr = net.IP(ip).String()
case 0x03: // 域名
len, err := readByte(conn)
if err != nil {
err = fmt.Errorf("读取域名长度失败:", err)
}
domain := make([]byte, len)
if _, err := io.ReadFull(conn, domain); err != nil {
err = fmt.Errorf("读取域名失败:", err)
}
addr = string(domain)
addr, err = DomainResolution(addr)
case 0x04: // IPv6
ip := make([]byte, 16)
if _, err := io.ReadFull(conn, ip); err != nil {
err = fmt.Errorf("读取IPv6地址失败:", err)
}
addr = net.IP(ip).String()
default:
err = fmt.Errorf("不支持的地址类型:", atyp)
}
if err != nil {
return "", 0, err
}
// 读取端口
portBytes := make([]byte, 2)
if _, err := io.ReadFull(conn, portBytes); err != nil {
return "", 0, fmt.Errorf("读取端口失败:", err)
}
destPort := uint16(portBytes[0])<<8 + uint16(portBytes[1])
return addr, int(destPort), nil
}
// 检查版本
func checkVersion(conn net.Conn) error {
// 读取SOCKS5代理协议的版本号
version, err := readByte(conn)
if err != nil {
return fmt.Errorf("读取版本号失败:%v", err)
}
// 只支持SOCKS5
if version != 0x05 {
return fmt.Errorf("不支持的SOCKS版本:", version)
}
return nil
}
// 认证
func auth(conn net.Conn) error {
// 读取客户端支持的认证方法数量
nmethods, err := readByte(conn)
if err != nil {
return fmt.Errorf("读取认证方法数量失败:", err)
}
// 跳过客户端支持的认证方法列表
_, err = io.CopyN(io.Discard, conn, int64(nmethods))
if err != nil {
return fmt.Errorf("跳过认证方法列表失败:", err)
}
// 选择无需认证(0x00)
if _, err := conn.Write([]byte{0x05, 0x00}); err != nil {
return fmt.Errorf("发送无需认证的响应失败:", err)
}
return nil
}
// readByte 从conn中读取单个字节,返回读取的字节和可能发生的错误。
func readByte(conn net.Conn) (byte, error) {
b := make([]byte, 1)
_, err := io.ReadFull(conn, b)
return b[0], err
}
// handleClient 处理来自客户端的连接。
func handleClient(conn net.Conn) {
defer conn.Close()
err := checkVersion(conn)
if err != nil {
log.Println(err)
return
}
err = auth(conn)
if err != nil {
log.Println(err)
return
}
err = checkVersion(conn)
if err != nil {
log.Println(err)
return
}
// 读取保留字段和地址类型
_, err = io.CopyN(io.Discard, conn, 2)
if err != nil {
log.Println("读取保留字段和地址类型失败:", err)
return
}
addr, port, err := getTargetIpPort(conn)
if err != nil{
log.Println(err)
return
}
if addr == ""{
return
}
// 连接目标服务器
server, err := dialWithSpecificLocalAddr(addr, localIP, port)
if err != nil {
log.Println("连接目标服务器失败:", err)
if _, err := conn.Write([]byte{0x05, 0x01, 0x00, 0x01, 0, 0, 0, 0, 0, 0}); err != nil {
log.Println("发送连接失败响应失败:", err)
}
return
}
defer server.Close()
// 发送成功响应
if _, err := conn.Write([]byte{0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0, 0}); err != nil {
log.Println("发送成功响应失败:", err)
return
}
// 数据转发
go io.Copy(conn, server)
io.Copy(server, conn)
}
func main() {
Init(os.Args[1])
// 监听本地1080端口
listener, err := net.Listen("tcp", ":1080")
if err != nil {
log.Fatal("监听端口失败:", err)
}
defer listener.Close()
log.Println("SOCKS5代理服务器正在监听1080端口...")
for {
// 接受客户端连接
client, err := listener.Accept()
if err != nil {
log.Println("接受客户端连接失败:", err)
continue
}
// 处理客户端连接
go handleClient(client)
}
}
评论已关闭