当前位置: 首页 > news >正文

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-简单的联表查询示例

假设我们有两个表&#xff0c;一个是users表&#xff0c;包含用户的ID和姓名&#xff1b;另一个是orders表&#xff0c;包含订单的ID、用户ID和订单金额。我们想要关联这两个表&#xff0c;查询出每个用户的订单总金额。 首先&#xff0c;我们可以使用以下SQL查询获取每个用户…...

Python基于joblib的并行计算进程线程multiprocessing多核并行计算

文章目录 Python基于joblib的并行计算适用场景使用示例总结爬虫&joblib使用`joblib`的场景注意事项使用实例结论joblib介绍简单示例多参数并行并行时CPU是怎么分配的何时选用并行进程&线程进程和线程之间的关系...

左右列的单元格合并

EasyExcel导出合并单元格&#xff0c;左右列的单元格合并 1、导出的实体类&#xff0c;也就是表头 Data public class CityCapacityPo {ExcelProperty(value "时间",index 0)private String time;ExcelProperty(value "出口",index 1)private String …...

机器学习 | 决策树 Decision Tree

—— 分而治之&#xff0c;逐个击破 把特征空间划分区域 每个区域拟合简单模型 分级分类决策 1、核心思想和原理 举例&#xff1a; 特征选择、节点分类、阈值确定 2、信息嫡 熵本身代表不确定性&#xff0c;是不确定性的一种度量。 熵越大&#xff0c;不确定性越高&#xff0c;…...

面试题总结(十四)【系统移植】【华清远见西安中心】

你用过哪些Bootloader&#xff1f;有什么区别&#xff1f; 作为一个AI助手&#xff0c;我没有直接使用过Bootloader。但我可以为您提供一些关于常见Bootloader的信息和他们之间的区别。 1. GRUB (GRand Unified Bootloader)&#xff1a;GRUB是一个功能强大且广泛使用的Bootload…...

【Spark精讲】Spark RDD弹性体现在哪些方面?

什么是“弹性”&#xff1f; 一般对于分布式系统&#xff0c;“弹性”指的是可以根据计算规模进行动态伸缩的特性。当计算量增长时&#xff0c;可以动态增加资源来满足计算需求&#xff0c;而当计算量减少时&#xff0c;又可以降低资源配置来节约成本。 参考&#xff1a;什么是…...

【从客户端理解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树在不同维度下的扩展。…...

非制冷红外成像技术实现高灵敏度和高分辨率

非制冷红外成像技术实现高灵敏度和高分辨率主要依赖于以下几个方面&#xff1a; 探测器设计&#xff1a;非制冷红外成像技术采用的探测器通常具有高灵敏度和高分辨率的特点。这些探测器能够有效地接收并转换红外辐射&#xff0c;从而产生高质量的图像信息。 光学系统设计&…...

@Resource 和 @Autowired区别是什么?

Resource 和 Autowired 时&#xff0c;它们都是用于依赖注入的注解&#xff0c;但它们有一些不同之处。 来源&#xff1a; Resource 是Java EE标准的一部分&#xff0c;而且是JDK提供的&#xff0c;不属于Spring框架的注解。它的使用范围更广泛&#xff0c;不仅可以用在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、转义字符&#xff1a;\n换行&#xff0c;\t前进一个tab键&#xff0c;\b退格键 2、八进制前面有0&#xff0c;%o或者%#o表示八进制&#xff0c;十六进制前有0X&#xff0c;%0x或者%#0x表示十六进制 3、%u打印无符号数&#xff0c;%g显示小数&#xff0c;类似于%f&#xff…...

zookeeper:启动后占用8080端口问题解决

ZooKeeper是一个分布式的&#xff0c;开放源码的分布式应用程序协调服务。它为分布式应用提供一致性服务的软件&#xff0c;提供的功能包括&#xff1a;配置维护、域名服务、分布式同步、组服务等。 我们经常在运行zookeeper服务时&#xff0c;不需要配置服务端口&#xff0c;…...

深度学习中的高斯分布

1 高斯分布数学表达 1.1 什么是高斯分布 高斯分布(Gaussian Distribution)又称正态分布(Normal Distribution)。高斯分布是一种重要的模型&#xff0c;其广泛应用于连续型随机变量的分布中&#xff0c;在数据分析领域中高斯分布占有重要地位。由于中心极限定理(Central Limit…...

【已解决】Atlas 导入 Hive 元数据,执行 import-hive.sh 报错

部署完 Atlas 之后&#xff0c;尝试导入 Hive 元数据&#xff0c;遇到了一些错误&#xff0c;特此记录一下&#xff0c;方便你我他。 执行 import-hive.sh 报错 [omchadoop102 apache-atlas-2.2.0]$ hook-bin/import-hive.sh Using Hive configuration directory [/opt/module…...

在 Windows PC 上轻松下载并安装 FFmpeg

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

21.Servlet 技术

JavaWeb应用的概念 在Sun的Java Servlet规范中&#xff0c;对Java Web应用作了这样定义&#xff1a;“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&#xff1a;事件监听器 1. 初始化监听器2. 创建事件发布器 SpringApplicationRunListeners3. 事件分发流程3.1 SimpleApplicationEventMulticaster#multicastEvent3.2 获取监听器 AbstractApplicationEventMulticaster#getApplicationListeners3.3 Abstra…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战

前言 现在我们有个如下的需求&#xff0c;设计一个邮件发奖的小系统&#xff0c; 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式&#xff08;Decorator Pattern&#xff09;允许向一个现有的对象添加新的功能&#xff0c;同时又不改变其…...

day52 ResNet18 CBAM

在深度学习的旅程中&#xff0c;我们不断探索如何提升模型的性能。今天&#xff0c;我将分享我在 ResNet18 模型中插入 CBAM&#xff08;Convolutional Block Attention Module&#xff09;模块&#xff0c;并采用分阶段微调策略的实践过程。通过这个过程&#xff0c;我不仅提升…...

【Java学习笔记】Arrays类

Arrays 类 1. 导入包&#xff1a;import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序&#xff08;自然排序和定制排序&#xff09;Arrays.binarySearch()通过二分搜索法进行查找&#xff08;前提&#xff1a;数组是…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)

0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述&#xff0c;后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作&#xff0c;其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)

服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

什么是库存周转?如何用进销存系统提高库存周转率?

你可能听说过这样一句话&#xff1a; “利润不是赚出来的&#xff0c;是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业&#xff0c;很多企业看着销售不错&#xff0c;账上却没钱、利润也不见了&#xff0c;一翻库存才发现&#xff1a; 一堆卖不动的旧货…...

对WWDC 2025 Keynote 内容的预测

借助我们以往对苹果公司发展路径的深入研究经验&#xff0c;以及大语言模型的分析能力&#xff0c;我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际&#xff0c;我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测&#xff0c;聊作存档。等到明…...

如何在看板中有效管理突发紧急任务

在看板中有效管理突发紧急任务需要&#xff1a;设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP&#xff08;Work-in-Progress&#xff09;弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中&#xff0c;设立专门的紧急任务通道尤为重要&#xff0c;这能…...

反射获取方法和属性

Java反射获取方法 在Java中&#xff0c;反射&#xff08;Reflection&#xff09;是一种强大的机制&#xff0c;允许程序在运行时访问和操作类的内部属性和方法。通过反射&#xff0c;可以动态地创建对象、调用方法、改变属性值&#xff0c;这在很多Java框架中如Spring和Hiberna…...

什么是Ansible Jinja2

理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具&#xff0c;可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板&#xff0c;允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板&#xff0c;并通…...