GO 的 socks5代理 编写
这里学习一下 socks5 代理的编写
网上有很多 学习一下
go 语言实战入门案例之实现Socks5 - 知乎
滑动验证页面
socks5协议原理学习-腾讯云开发者社区-腾讯云 (tencent.com)
首先我们要了解一下socks5的代理方式
socks5 是基于
- 认证
- 建立连接
- 转发数据
所形成的代理 我们只需要按照这三个写出代码即可
首先就是socks5的认证
Socks5Atuth
这里首先要认证 那么我们首先要确定是不是socks5代理
在socks5中 前两个字节 分别是 socks版本号 和 支持的认证方式
前面两个 1
所以这里我们开始读取前面的 版本号 ver socks5是固定值 0x05
这里开始编写一下监听
package mainimport ("bufio""fmt""log""net"
)const socks5Ver = 0x05
const cmdVer = 0x01
const aytpVerIpv4 = 0x01
const aytpVerUrl = 0x03 //这里是下面的常量 不需要理会即可 当作值即可func main() {server, err := net.Listen("tcp", "127.0.0.1:1080")if err != nil {panic(err)}for {client, err := server.Accept()if err != nil {log.Printf("Accpet error :", err)continue}//确定ip端口 进行链接后 开始进程fmt.Println("开始监听", client, client.RemoteAddr())}
}
然后开始处理数据
首先我们需要开启一个协程 处理
func process(conn net.Conn) {defer conn.Close()readio := bufio.NewReader(conn)err := auth(readio, conn)
}
这里我们首先处理一下认证的信息
// +----+----------+----------+// |VER | NMETHODS | METHODS |// +----+----------+----------+// | 1 | 1 | 1 to 255 |// +----+----------+----------+// VER: 协议版本,socks5为0x05// NMETHODS: 支持认证的方法数量// METHODS: 对应NMETHODS,NMETHODS的值为多少,METHODS就有多少个字节。RFC预定义了一些值的含义,内容如下:// X’00’ NO AUTHENTICATION REQUIRED// X’02’ USERNAME/PASSWORD// 版本和NMETHODS值都是单字节的,所以ReadByte读一个字节就好了
这里需要认证的东西就是这些 我们首先进行认证 ver
func auth(readio *bufio.Reader, conn net.Conn) (err error) {ver, err := readio.ReadByte()fmt.Println(ver)return nil
}
这里是通过 readbyte 读取一个字节 我们输出一下就知道是多少了
发现我们通过浏览器进行代理 第一个byte是 5 对应 socks5
如果将代理设置为 socks4 那么这里就是对应4
然后这里进行匹配 如果不是就输出错误 这样 ver认证就结束了
认证的ver
func auth(readio *bufio.Reader, conn net.Conn) (err error) {ver, err := readio.ReadByte()if err != nil {return fmt.Errorf("ver error:", err)}if ver != socks5Ver {return fmt.Errorf("ver num error: ", err)}}
认证method
这里是socks5的认证,是否需要认证
methodSize, err := readio.ReadByte()fmt.Println(methodSize)return
其实这里就是读取一个字节的大小
func auth(readio *bufio.Reader, conn net.Conn) (err error) {ver, err := readio.ReadByte()if err != nil {return fmt.Errorf("ver error:", err)}if ver != socks5Ver {return fmt.Errorf("ver num error: ", err)}methodSize, err := readio.ReadByte() //确定切片大小 为 1字节method := make([]byte, methodSize) //创建一个大小的切片_, err = io.ReadFull(readio, method) // 这里是判断是否读了if err != nil {return fmt.Errorf("read method error :", err)}_, err = conn.Write([]byte{socks5Ver, 0x00}) // 这里是握手的回复 说明我们不需要认证if err != nil {return fmt.Errorf("write error:", err)}return nil
}
这里注意
_, err = conn.Write([]byte{socks5Ver, 0x00})
这里其实是监听后告诉 不需要进行 认证
当我们认证完后开始处理浏览器的报文
Socks5Connect
// 读取浏览器发送的报文// +----+-----+-------+------+----------+----------+// |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT |// +----+-----+-------+------+----------+----------+// | 1 | 1 | X'00' | 1 | Variable | 2 |// +----+-----+-------+------+----------+----------+// VER 版本号,socks5的值为0x05// CMD 0x01表示CONNECT请求// RSV 保留字段,值为0x00// ATYP 目标地址类型,DST.ADDR的数据对应这个字段的类型。// 0x01表示IPv4地址,DST.ADDR为4个字节// 0x03表示域名,DST.ADDR是一个可变长度的域名// DST.ADDR 一个可变长度的值// DST.PORT 目标端口,固定2个字节这里是浏览器发送的报文 我们依旧先进行鉴定
func connnect(readio *bufio.Reader, conn net.Conn) (err error) {buf := make([]byte, 4)_, err = io.ReadFull(readio, buf) // 这里是读取字节数 读取前面4个作为一个切片if err != nil {return fmt.Errorf("read header error :", err)}var ver, cmd, atyp = buf[0], buf[1], buf[3] // 这里对应报文的字节认证的位置fmt.Println(ver, cmd, atyp)return
}
这里就很明显了 5 对应 socks5 1 对应 链接的请求 3 对应 url 是一个域名
+----+--------+-------------------+--------------+---------------+
|VER | CMD | ATYP | HOST SIZE | HOST |
+----+--------+-------------------+--------------+---------------+
| 05 | 01 | 03 | 11 | www.exa.com |
+----+--------+-------------------+--------------+---------------+首先之前的都已经被读了ver cmdatyp然后再读 就是 host size 这里是 后面 host 的地址长度
这里开源发现 cn.bing.com的长度是11 因为url是可变的 所以后面的host也是可变的
我们首先读取字节长度 然后作为 值传递给切片 读取该长度的值 这样我们就开源获取到url地址
_, err = io.ReadFull(readio, buf[:2]) //再向后读取两个字节 是portif err != nil {return fmt.Errorf("port error:", err)}port := binary.BigEndian.Uint16(buf[:2]) //这里是大端序监听端口fmt.Println(port)fmt.Println(addr)return
这里的原理是这样的
首先我们读取两个字节
443 [1 187]
然后进行大端序排序 0 在高 80 在低
这个时候就是
[1 187]
然后我们进uint16处理
[1 187]将高位字节(1)左移 8 位,使其占据 uint16 的高 8 位,得到结果 00000001 00000000将低位字节(187)放在 uint16 的低 8 位,得到结果 00000001 1011101100000001 10111011443
这样我们就获取到了端口
然后我们就可以进行拼接url
dest := fmt.Sprintf("%v:%v", addr, port) fmt.Println(dest)
然后我们开始建立tcp请求
dest, err := net.Dial("tcp", fmt.Sprintf("%v:%v", addr, port)) //建立tcp协议if err != nil {return fmt.Errorf("dial error:", err)}defer dest.Close()log.Println("访问:", addr, port)
完整代码
package mainimport ("bufio""context""encoding/binary""fmt""io""log""net"
)const socks5Ver = 0x05
const cmdVer = 0x01
const aytpVerIpv4 = 0x01
const aytpVerUrl = 0x03func main() {server, err := net.Listen("tcp", "127.0.0.1:1080")if err != nil {panic(err)}for {client, err := server.Accept()if err != nil {log.Printf("Accpet error :", err)continue}//确定ip端口 进行链接后 开始进程fmt.Println("开始监听")go process(client)}
}
func process(conn net.Conn) {defer conn.Close()readio := bufio.NewReader(conn)err := auth(readio, conn)if err != nil {fmt.Errorf("ip: %v,auth error :", conn.RemoteAddr().String(), err)}err = connnect(readio, conn)
}func auth(readio *bufio.Reader, conn net.Conn) (err error) {ver, err := readio.ReadByte()if err != nil {return fmt.Errorf("ver error:", err)}if ver != socks5Ver {return fmt.Errorf("ver num error: ", err)}methodSize, err := readio.ReadByte() //确定切片大小 为 1字节method := make([]byte, methodSize) //创建一个大小的切片_, err = io.ReadFull(readio, method) // 这里是判断是否读了if err != nil {return fmt.Errorf("read method error :", err)}_, err = conn.Write([]byte{socks5Ver, 0x00}) // 这里是握手的回复 说明我们不需要认证if err != nil {return fmt.Errorf("write error:", err)}return nil
}func connnect(readio *bufio.Reader, conn net.Conn) (err error) {buf := make([]byte, 4)_, err = io.ReadFull(readio, buf) // 这里是读取字节数 读取前面4个作为一个切片if err != nil {return fmt.Errorf("read header error :", err)}var ver, cmd, atyp = buf[0], buf[1], buf[3] // 这里对应报文的字节认证的位置if ver != socks5Ver {return fmt.Errorf("connect ver error:", err)}if cmd != cmdVer {return fmt.Errorf("connect cmd error:", err)}addr := ""switch atyp {case aytpVerIpv4:_, err = io.ReadFull(readio, buf)if err != nil {return fmt.Errorf("ipv4 error:", err)}addr = fmt.Sprintf("%d.%d.%d.%d", buf[0], buf[1], buf[2], buf[3]) //读取ip地址case aytpVerUrl: //这里解析的是urlhostSize, err := readio.ReadByte() //获取url的字节长度if err != nil {return fmt.Errorf("read hostSize failed:%w", err)}host := make([]byte, hostSize) //获取url字符的字节_, err = io.ReadFull(readio, host)if err != nil {return fmt.Errorf("read host failed:%w", err)}addr = string(host)default:return fmt.Errorf("not yet", atyp)}_, err = io.ReadFull(readio, buf[:2]) //再向后读取两个字节 是portif err != nil {return fmt.Errorf("port error:", err)}port := binary.BigEndian.Uint16(buf[:2]) //这里是大端序监听端口dest, err := net.Dial("tcp", fmt.Sprintf("%v:%v", addr, port)) //建立tcp协议if err != nil {return fmt.Errorf("dial error:", err)}defer dest.Close()log.Println("访问:", addr, port)_, err = conn.Write([]byte{0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0, 0})if err != nil {return fmt.Errorf("写入错误:", err)}ctx, cancel := context.WithCancel(context.Background()) //启动一个可以取消的上下文功能defer cancel()go func() {_, _ = io.Copy(dest, readio) //这里是从我们的请求中读取出来 写入请求中cancel()}()go func() {_, _ = io.Copy(conn, dest) //这里从请求中写入返回报文中cancel()}()<-ctx.Done() // 这里是 只要管道输出内容了就停止 所以上面两个协程 只要有一个输出 就取消return nil
}
相关文章:

GO 的 socks5代理 编写
这里学习一下 socks5 代理的编写 网上有很多 学习一下 go 语言实战入门案例之实现Socks5 - 知乎 滑动验证页面 socks5协议原理学习-腾讯云开发者社区-腾讯云 (tencent.com) 首先我们要了解一下socks5的代理方式 socks5 是基于 认证建立连接转发数据 所形成的代理 我们只…...
MYSQL-简单的联表查询示例
假设我们有两个表,一个是users表,包含用户的ID和姓名;另一个是orders表,包含订单的ID、用户ID和订单金额。我们想要关联这两个表,查询出每个用户的订单总金额。 首先,我们可以使用以下SQL查询获取每个用户…...
Python基于joblib的并行计算进程线程multiprocessing多核并行计算
文章目录 Python基于joblib的并行计算适用场景使用示例总结爬虫&joblib使用`joblib`的场景注意事项使用实例结论joblib介绍简单示例多参数并行并行时CPU是怎么分配的何时选用并行进程&线程进程和线程之间的关系...
左右列的单元格合并
EasyExcel导出合并单元格,左右列的单元格合并 1、导出的实体类,也就是表头 Data public class CityCapacityPo {ExcelProperty(value "时间",index 0)private String time;ExcelProperty(value "出口",index 1)private String …...

机器学习 | 决策树 Decision Tree
—— 分而治之,逐个击破 把特征空间划分区域 每个区域拟合简单模型 分级分类决策 1、核心思想和原理 举例: 特征选择、节点分类、阈值确定 2、信息嫡 熵本身代表不确定性,是不确定性的一种度量。 熵越大,不确定性越高,…...
面试题总结(十四)【系统移植】【华清远见西安中心】
你用过哪些Bootloader?有什么区别? 作为一个AI助手,我没有直接使用过Bootloader。但我可以为您提供一些关于常见Bootloader的信息和他们之间的区别。 1. GRUB (GRand Unified Bootloader):GRUB是一个功能强大且广泛使用的Bootload…...
【Spark精讲】Spark RDD弹性体现在哪些方面?
什么是“弹性”? 一般对于分布式系统,“弹性”指的是可以根据计算规模进行动态伸缩的特性。当计算量增长时,可以动态增加资源来满足计算需求,而当计算量减少时,又可以降低资源配置来节约成本。 参考:什么是…...
【从客户端理解Kafka的使用方式】
文章目录 一、从基础的客户端说起1、消息发送者主流程2、消息消费者主流程 二、从客户端属性来梳理客户端工作机制1、消费者分组消费机制2、生产者拦截器机制3、消息序列化机制4、消息分区路由机制5、生产者消息缓存机制6、发送应答机制 三、客户端流程总结四、SpringBoot集成K…...

『OPEN3D』1.5.4 动手实现点云八叉树(OctoTree)最近邻
本专栏地址: https://blog.csdn.net/qq_41366026/category_12186023.html?spm=1001.2014.3001.5482 在二维和三维空间中,我们可以采用四叉树(Quad tree)和八叉树(Octree)这两种特定的数据结构来处理空间分割。这些树形结构可以看作是K-d树在不同维度下的扩展。…...
非制冷红外成像技术实现高灵敏度和高分辨率
非制冷红外成像技术实现高灵敏度和高分辨率主要依赖于以下几个方面: 探测器设计:非制冷红外成像技术采用的探测器通常具有高灵敏度和高分辨率的特点。这些探测器能够有效地接收并转换红外辐射,从而产生高质量的图像信息。 光学系统设计&…...
@Resource 和 @Autowired区别是什么?
Resource 和 Autowired 时,它们都是用于依赖注入的注解,但它们有一些不同之处。 来源: Resource 是Java EE标准的一部分,而且是JDK提供的,不属于Spring框架的注解。它的使用范围更广泛,不仅可以用在Spring中…...
K8S的一个pod中运行多个容器
通过deployment的方式部署 创建一个deployment文件 [rootk8s-master1 pods]# cat app.yaml apiVersion: apps/v1 kind: Deployment metadata:name: dsfnamespace: applabels:app: dsf spec:replicas: 1 #实例的个数selector:matc…...

《每天一分钟学习C语言·一》
1、转义字符:\n换行,\t前进一个tab键,\b退格键 2、八进制前面有0,%o或者%#o表示八进制,十六进制前有0X,%0x或者%#0x表示十六进制 3、%u打印无符号数,%g显示小数,类似于%fÿ…...

zookeeper:启动后占用8080端口问题解决
ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务。它为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。 我们经常在运行zookeeper服务时,不需要配置服务端口,…...

深度学习中的高斯分布
1 高斯分布数学表达 1.1 什么是高斯分布 高斯分布(Gaussian Distribution)又称正态分布(Normal Distribution)。高斯分布是一种重要的模型,其广泛应用于连续型随机变量的分布中,在数据分析领域中高斯分布占有重要地位。由于中心极限定理(Central Limit…...
【已解决】Atlas 导入 Hive 元数据,执行 import-hive.sh 报错
部署完 Atlas 之后,尝试导入 Hive 元数据,遇到了一些错误,特此记录一下,方便你我他。 执行 import-hive.sh 报错 [omchadoop102 apache-atlas-2.2.0]$ hook-bin/import-hive.sh Using Hive configuration directory [/opt/module…...

在 Windows PC 上轻松下载并安装 FFmpeg
FFmpeg 是一种开源媒体工具,可用于将任何视频格式转换为您需要的格式。该工具只是命令行,因此它没有图形、可点击的界面。如果您习惯使用常规图形 Windows 程序,安装 FFmpeg 一开始可能看起来很复杂,但不用担心,它;很简…...

21.Servlet 技术
JavaWeb应用的概念 在Sun的Java Servlet规范中,对Java Web应用作了这样定义:“Java Web应用由一组Servlet、HTML页、类、以及其它可以被绑定的资源构成。它可以在各种供应商提供的实现Servlet规范的 Servlet容器 中运行。” Java Web应用中可以包含如下…...

【Hive】——DDL(PARTITION)
1 增加分区 1.1 添加一个分区 ALTER TABLE t_user_province ADD PARTITION (provinceBJ) location/user/hive/warehouse/test.db/t_user_province/provinceBJ;必须自己把数据加载到增加的分区中 hive不会帮你添加 1.2 一次添加多个分区 ALTER TABLE table_name ADD PARTITION…...
SpringBoot 源码解析4:事件监听器
SpringBoot 源码解析4:事件监听器 1. 初始化监听器2. 创建事件发布器 SpringApplicationRunListeners3. 事件分发流程3.1 SimpleApplicationEventMulticaster#multicastEvent3.2 获取监听器 AbstractApplicationEventMulticaster#getApplicationListeners3.3 Abstra…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

CMake基础:构建流程详解
目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...

ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...
LRU 缓存机制详解与实现(Java版) + 力扣解决
📌 LRU 缓存机制详解与实现(Java版) 一、📖 问题背景 在日常开发中,我们经常会使用 缓存(Cache) 来提升性能。但由于内存有限,缓存不可能无限增长,于是需要策略决定&am…...

协议转换利器,profinet转ethercat网关的两大派系,各有千秋
随着工业以太网的发展,其高效、便捷、协议开放、易于冗余等诸多优点,被越来越多的工业现场所采用。西门子SIMATIC S7-1200/1500系列PLC集成有Profinet接口,具有实时性、开放性,使用TCP/IP和IT标准,符合基于工业以太网的…...
深入解析 ReentrantLock:原理、公平锁与非公平锁的较量
ReentrantLock 是 Java 中 java.util.concurrent.locks 包下的一个重要类,用于实现线程同步,支持可重入性,并且可以选择公平锁或非公平锁的实现方式。下面将详细介绍 ReentrantLock 的实现原理以及公平锁和非公平锁的区别。 ReentrantLock 实现原理 基本架构 ReentrantLo…...
【向量库】Weaviate 搜索与索引技术:从基础概念到性能优化
文章目录 零、概述一、搜索技术分类1. 向量搜索:捕捉语义的智能检索2. 关键字搜索:精确匹配的传统方案3. 混合搜索:语义与精确的双重保障 二、向量检索技术分类1. HNSW索引:大规模数据的高效引擎2. Flat索引:小规模数据…...
Ubuntu挂载本地镜像源(像CentOS 一样挂载本地镜像源)
1.挂载 ISO 镜像 sudo mount -o loop /ubuntu-22.04.5-desktop-amd64.iso /mnt/iso 2.备份现有的软件源配置文件: sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak 3.编辑软件源配置文件 编辑 /etc/apt/sources.list sudo nano /etc/apt/sources.l…...