如何在 socks5 代理中将 2 个字节的端口号返回给客户端?

Posted

技术标签:

【中文标题】如何在 socks5 代理中将 2 个字节的端口号返回给客户端?【英文标题】:How to return the port number in 2 bytes to client in socks5 proxy? 【发布时间】:2017-12-31 04:18:52 【问题描述】:

我正在尝试实现 socks5 代理服务器。 根据 rfc,大多数事情都很清楚,但我被困在解释客户端端口并以字节为单位写入端口号。

我做了一个函数,它需要一个 int 并返回 2 个字节。此函数首先将数字转换为二进制,然后将位拆分为字符串,然后将它们转换回字节。但这似乎是错误的,因为如果最右边的位为 0,它们就会丢失。 这是函数

func getBytesOfInt(i int) []byte 
    binary := fmt.Sprintf("%b", i)
    if i < 255 
        return []bytebyte(i)
    
    first := binary[:8]
    last := binary[9:]
    fmt.Println(binary, first, last)
    i1, _ := strconv.ParseInt(first, 2, 64)
    i2, _ := strconv.ParseInt(last, 2, 64)
    return []bytebyte(i1), byte(i2)

你能解释一下我应该如何解析数字并获得 2 个字节,最重要的是我如何将它转换回整数。

目前,如果您为此函数提供 1024,它将返回 []byte0x80, 0x0,即十进制的 128,但正如您所见,正确的位丢失了,只有一个无用的 0。

【问题讨论】:

Convert an integer to a byte array的可能重复 这是许多将整数转换为二进制问题的副本,例如***.com/questions/16888357/…。看看 encoding/binary 包,它比一个字符串然后返回要高效得多。 @Matthias247 binary.Write 结果对我的情况完全不可用,它给了我比我需要的更多的字节数 然后只使用你需要的字节。或者在转换为二进制之前转换为short。 github.com/golang/net/tree/master/proxy 中的代码可能对您有用。请参阅协议服务器端的 _test.go 文件。 【参考方案1】:

您的代码有多个问题。第一个:8 和 9:错过一个元素([8]),见:https://play.golang.org/p/yuhh4ZeJFNL

而且,您应该将第二个字节作为 int 的低字节插入,将第一个字节作为高字节插入,而不是从字面上切割二进制字符串。例如 4 应该被替换为 [0x0,0x4] 而不是 [0x4,0x0] 应该是 1024。

如果你想继续使用 strconv,你应该使用:

n := len(binary)
first := binary[:n-8]
last := binary[n-8:]

但是效率很低。

我建议b[0],b[1] = i &gt;&gt; 8, i &amp; 255i = b[0]&lt;&lt;8 + b[1]

【讨论】:

您能解释一下所有按位运算的情况吗?是否有任何资源可以让我了解有关这些运算的更多信息?我仍然很难理解我们为什么以及如何使用按位运算。所有资源都解释了我完全理解的它们所做的事情,但没有一个提到为什么我们需要对二进制进行这些操作。在您的示例中,我理解第二部分将 b[0] 向左移动 8 位并添加 b[1],这很有意义,但第一部分我完全丢失了 @leafBebop 你的意思是低和高字节,而不是'位'。 255 基本上是 11111111 ,它是低字节的掩码。这是一个相当简单的位运算。要了解为什么需要位操作,您可能需要了解机器的工作原理、字节是什么以及整数是如何存储的。但是,我没有用英语学习所有这些,所以我不能推荐资源。

以上是关于如何在 socks5 代理中将 2 个字节的端口号返回给客户端?的主要内容,如果未能解决你的问题,请参考以下文章

怎样设置socks代理

如何使用SOCKS5代理服务器

SOCKS5代理 的含义是?地址,端口是啥?HTTP代理又是啥,它的地址,端口又该怎样填写?

常用的端口号

Qt WebEngine设置socks5代理

如何修改即时聊天websocket的端口号