我正在尝试通过TcpClient通过SOCKS5代理连接到www.google.com:443,但是对于为什么我的CONNECT请求在被代理挂起时感到困惑。在通过SOCKS5代理连接之前,下面提供的代码可以正常工作(如果使用常规HTTP代理,则可以正常工作)。
Public Sub SocksProxyTest(proxy As String, proxyPort As String)
Const host As String = "www.google.com"
Const hostPort As Integer = 443
Dim buffer As Byte() = New Byte(2047) {}
Dim bytes As Integer
Dim client As TcpClient = New TcpClient(proxy, proxyPort)
Dim stream As NetworkStream = client.GetStream()
Debug.Print("negotiating socks5 connection")
Using br = New BinaryReader(stream, Encoding.[Default], True)
Dim ip = Dns.GetHostAddresses(host)(0)
Dim auth As Byte() = New Byte() {&H5, &H1, &H0}
Debug.Print(">> " & String.Join(" ", auth.Select(Function(b) "&H" & b.ToString("X2"))))
stream.Write(auth, 0, auth.Length)
Dim result As Byte() = br.ReadBytes(2)
Debug.Print("<< &H" & result(1).ToString("X2"))
Dim data As Byte() = {&H5, &H1, &H0, &H1, &H0, &H0, &H0, &H0, get_port_bytes(hostPort)(0), get_port_bytes(hostPort)(1)}
For i As Integer = 0 To 4 - 1
data(i + 4) = ip.GetAddressBytes()(i)
Next
Debug.Print(">> " & String.Join(" ", data.Select(Function(b) "&H" & b.ToString("X2"))))
stream.Write(data, 0, data.Length)
stream.Flush()
result = br.ReadBytes(10)
Debug.Print("<< &H" & result(1).ToString("X2"))
br.Close()
End Using
Debug.Print("negotiated socks5 connection")
Debug.Print("sending tunnel request")
Dim tunnelRequest As Byte() = Encoding.UTF8.GetBytes(String.Format("CONNECT {0}:{1} HTTP/1.1{2}Host: {0}{2}{2}", host, hostPort, vbCrLf))
stream.Write(tunnelRequest, 0, tunnelRequest.Length)
stream.Flush()
bytes = stream.Read(buffer, 0, buffer.Length)
Console.Write(Encoding.UTF8.GetString(buffer, 0, bytes))
Dim sslStream As SslStream = New SslStream(stream)
sslStream.AuthenticateAsClient(host)
Debug.Print("sending web request")
Dim request As Byte() = Encoding.UTF8.GetBytes(String.Format("GET https://{0}/ HTTP/1.1" & vbCrLf & "Host: {0}" & vbCrLf & vbCrLf, host))
sslStream.Write(request, 0, request.Length)
sslStream.Flush()
Do
bytes = sslStream.Read(buffer, 0, buffer.Length)
Debug.Print(Encoding.UTF8.GetString(buffer, 0, bytes))
Loop While bytes <> 0
client.Close()
End Sub
答案 0 :(得分:0)
您为什么要发送CONNECT
请求?该动词仅在通过HTTP代理连接时使用,而在通过SOCKS代理连接时使用。
由于您没有将SOCKS代理连接到HTTP代理,因此完全摆脱了CONNECT
请求,因此它不属于这里。只需让SOCKS代理直接连接到目标主机即可(FYI,在SOCKS v4a和v5中,您可以并且应该将目标主机名发送到代理,并让它为您解析IP,DON “请自己解决,否则您可能会得到错误的IP,甚至遇到解析失败的情况。”
一旦代理服务器连接到目标主机,就可以根据需要与目标主机正常通信,就像您已经直接连接到目标主机一样。
请尝试以下类似操作:
Public Sub SocksProxyTest(proxy As String, proxyPort As String)
Const host As String = "www.google.com"
Const hostPort As Integer = 443
Dim buffer As Byte() = New Byte(2047) {}
Dim bytes As Integer
Dim client As TcpClient = New TcpClient(proxy, proxyPort)
Dim stream As NetworkStream = client.GetStream()
Debug.Print("negotiating socks5 connection")
Using br = New BinaryReader(stream, Encoding.[Default], True)
Dim auth As Byte() = New Byte() {&H5, &H1, &H0}
Debug.Print(">> " & String.Join(" ", auth.Select(Function(b) "&H" & b.ToString("X2"))))
stream.Write(auth, 0, auth.Length)
Dim result As Byte() = br.ReadBytes(2)
Debug.Print("<< &H" & result(1).ToString("X2"))
If result(1) <> &H0 Then
client.Close()
Exit Sub
End If
Dim host_bytes As Byte() = Encoding.ASCII.GetBytes(host)
Dim port_bytes As Byte() = get_port_bytes(hostPort)
Dim data As Byte() = New Byte(7 + host_bytes.Length) {}
data(0) = &H5
data(1) = &H1
data(2) = &H0
data(3) = &H3
data(4) = CByte(host_bytes.Length)
host_bytes.CopyTo(data, 5)
port_bytes.CopyTo(data, 5 + host_bytes.Length)
Debug.Print(">> " & String.Join(" ", data.Select(Function(b) "&H" & b.ToString("X2"))))
stream.Write(data, 0, data.Length)
stream.Flush()
result = br.ReadBytes(4)
Debug.Print("<< &H" & result(1).ToString("X2"))
If result(1) <> &H0 Then
client.Close()
Exit Sub
End If
Select result(3)
Case &H1
br.ReadBytes(4)
Case &H3
br.ReadBytes(br.ReadByte())
Case &H4
br.ReadBytes(16)
End Select
br.ReadBytes(2)
br.Close()
End Using
Debug.Print("negotiated socks5 connection")
Dim sslStream As SslStream = New SslStream(stream)
sslStream.AuthenticateAsClient(host)
Debug.Print("sending web request")
Dim request As Byte() = Encoding.UTF8.GetBytes(String.Format("GET / HTTP/1.1" & vbCrLf & "Host: {0}" & vbCrLf & "Connection: close" & vbCrLf & vbCrLf, host))
sslStream.Write(request, 0, request.Length)
sslStream.Flush()
Do
bytes = sslStream.Read(buffer, 0, buffer.Length)
Debug.Print(Encoding.UTF8.GetString(buffer, 0, bytes))
Loop While bytes <> 0
client.Close()
End Sub