3 回答
TA贡献1851条经验 获得超5个赞
要通过不理解它的代理来隧道 HTTP/2,您需要使用 HTTP/1.1 进行初始连接,然后仅在隧道中使用 HTTP/2。您的代码从一开始就使用 HTTP/2,这是行不通的。
要真正建立该隧道,您首先向目标主机发送 HTTP CONNECT 请求,并收到 200 响应,然后将来连接上的所有其他内容都会在您和目标主机之间来回转发。
一旦你的隧道工作了,你就可以发送 HTTP/2(或目标服务器理解的任何其他内容),它会直接到达你的目标。
在节点中执行此操作的代码如下所示:
const http = require('http');
const http2 = require('http2');
// Build a HTTP/1.1 CONNECT request for a tunnel:
const req = http.request({
method: 'CONNECT',
host: '127.0.0.1',
port: 8888,
path: 'cypher.codes'
});
req.end(); // Send it
req.on('connect', (res, socket) => {
// When you get a successful response, use the tunnelled socket
// to make your new request.
const client = http2.connect('https://cypher.codes', {
// Use your existing socket, wrapped with TLS for HTTPS:
createConnection: () => tls.connect({
socket: socket,
ALPNProtocols: ['h2']
})
});
// From here, use 'client' to do HTTP/2 as normal through the tunnel
});
我最近也一直在研究我自己的工具的内部结构,为代理添加完整的 HTTP/2 支持,并将其写在这里,这可能对你非常重要。https://github.com/httptoolkit/mockttp/blob/h2/test/integration/http2.spec.ts中的测试在这样的节点中有更多和更大的隧道 HTTP/2 示例,所以这些绝对值得也看看。当然,这一切仍在开发中,所以如果您有任何问题或发现任何错误,请告诉我。
TA贡献1775条经验 获得超8个赞
身份验证以及如何避免 TLS 证书错误。
所以这是我的更新版本:
const http = require('http');
const http2 = require('http2');
const tls = require('tls');
// Build a HTTP/1.1 CONNECT request for a tunnel:
const username = '...';
const password = '...';
const req = http.request({
method: 'CONNECT',
host: '127.0.0.1',
port: 8888,
path: 'website.com', //the destination domain
headers: { //this is how we authorize the proxy, skip it if you don't need it
'Proxy-Authorization': 'Basic ' + Buffer.from(username + ':' + password).toString('base64')
}
});
req.end(); // Send it
req.on('connect', (res, socket) => {
// When you get a successful response, use the tunnelled socket to make your new request
const client = http2.connect('https://website.com', {
createConnection: () => tls.connect({
host: 'website.com', //this is necessary to avoid certificate errors
socket: socket,
ALPNProtocols: ['h2']
})
});
// From here, use 'client' to do HTTP/2 as normal through the tunnel
});
TA贡献1790条经验 获得超9个赞
为了显示我的解决方案,我们将向 API 发出请求,该 API 将您的 IP 作为 JSON 返回,然后您就可以适应您的需求。
这是代码:
/**
* A URL without the path.
*/
const TARGET_AUTHOTIRY = 'https://api4.my-ip.io'
/**
* You should use the host with the port equivalent to the protocol
* HTTP => 80
* HTTPS => 443
*/
const TARGET_HOST = 'api4.my-ip.io:443'
/**
* Proxy configuration
*/
const PROXY_HOST = '<your_proxy_host>'
const PROXY_PORT = '<your_proxy_port>'
const PROXY_USERNAME = '<your_proxy_username>'
const PROXY_PASSWORD = '<your_proxy_password>'
/**
* Establishes an connection to the target server throught the HTTP/1.0
* proxy server.
*
* The CONNECT method tells the PROXY server where this connection should arive.
*
* After the connection is established you will be able to use the TCP socket to send data
* to the TARGET server.
*/
const request = http.request({
method: 'CONNECT',
host: PROXY_HOST,
port: PROXY_PORT,
path: TARGET_HOST,
headers: {
'Host': TARGET_HOST,
'Proxy-Authorization': `Basic ${Buffer.from(`${PROXY_USERNAME}:${PROXY_PASSWORD}`).toString('base64')}`
}
})
/**
* Wait the "connect" event and then uses the TCP socket to proxy the HTTP/2.0 connection throught.
*/
request.on('connect', (res, socket) => {
/**
* Check if it has successfully connected to the server
*/
if (res.statusCode !== 200)
throw new Error('Connection rejected by the proxy')
/**
* Use the TCP socket from the HTTP/1.0 as the socket for this new connection
* without the need to establish the TLS connection manually and handle the errors
* manually too.
*
* This method accepts all TCP and TLS options.
*/
const client = http2.connect(TARGET_AUTHOTIRY, { socket })
client.on('connect', () => {
console.log('Connected to the page!')
})
/**
* Request to check your IP
*/
const req = client.request({
':path': '/ip.json',
})
req.on('response', (headers) => {
console.log('Recieved a response')
})
/**
* Stores the data recieved as a response
*/
const buffers = []
req.on('data', (buffer) => {
buffers.push(buffer)
})
req.on('end', () => {
console.log(Buffer.concat(buffers).toString('utf-8'))
// Closes the connection with the server
client.close()
})
req.end()
})
request.end()
我没有创建 TLS 套接字,而是将我的 TCP 套接字注入 HTTP/2.0 客户端。
socket选项未在方法文档中明确列出,但该方法接受所有net.connect ()和tls.connect()选项。
您可以在此处找到有关http2.connect方法的所有文档:HTTP 2 Node JS Documentation
添加回答
举报
