Http 代理穿透

原理

HTTP代理服务器中能够提供一种HTTP CONNECT代理服务,能够允许用户建立TCP连接到任何端口。通过CONNECT方法穿透代理的实现方法为:

CONNECT代理服务器的代理端口(如:8080);如果成功返回就可以按照正常的Socket进行通讯。当然在此之前需要先获得代理相关的信息。

如何获取HTTP代理相关信息

程序中是通过读取注册表来获取计算机HTTP代理相关信息的,在注册表的\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings键值下就保存着HTTP代理服务器及端口等信息,

根据该键值下的ProxyEnable值可以判断是否有HTTP代理,没有代理的情况下ProxyEnable值为0。

当然一般情况下程序去中访问该键值可能是受限的,所有就需要获取到访问令牌不受限制的UserSid,使用该UserSid去读取HTTP代理信息。

cpp 复制代码
char tmpBuffer[128] = { 0 };
	::sprintf(tmpBuffer, "CONNECT %s:%d HTTP/1.1\r\nUser-Agent: Mozilla/4.0\r\nConnection: Keep-Alive\r\n\r\n", ip.c_str(), port);
	Send(tmpBuffer, strlen(tmpBuffer));
	Receive(tmpBuffer, sizeof(tmpBuffer));

实现

头文件

cpp 复制代码
#pragma once

#include <string>
#include <vector>

using namespace std;

class addrinfo;

class CHttpProxy
{
public:
	CHttpProxy(std::string ip, unsigned short port)
		:m_proxyIp(ip), m_proxyPort(port), m_socket(-1)
	{}

	~CHttpProxy(void);

	void ConnectProxyServer();
	void ConnectServer(std::string ip, unsigned short port);

	bool Send(const char* buf, int len);
	int Receive(char* buf, int bufLen);

	int GetSocket()
	{
		return m_socket;
	}
private:
	std::string m_proxyIp;
	addrinfo* m_addrinfo = nullptr;
	unsigned short m_proxyPort;
	int m_socket;
};

实现

cpp 复制代码
#include "HttpProxy.h"
#include <string.h>

#include <time.h>
#ifdef WIN32
#include <WS2tcpip.h>
#else 
#include <unistd.h>
#include <netdb.h> 
#include <arpa/inet.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>  
#define INVALID_SOCKET -1
#endif

CHttpProxy::~CHttpProxy(void)
{
	if (m_addrinfo)
	{
		freeaddrinfo(m_addrinfo);
	}
}
void CHttpProxy::ConnectProxyServer()
{
	struct sockaddr_in addr;
	m_socket = socket(AF_INET, SOCK_STREAM, 0);
	if (m_socket == INVALID_SOCKET)
	{
		throw CException("Error on creating socket fd");
	}
	
	addrinfo inAddrInfo = { 0 };
	inAddrInfo.ai_family = AF_INET;
	inAddrInfo.ai_socktype = SOCK_STREAM;

	std::string strPort = std::to_string(m_proxyPort);
	if (getaddrinfo(m_proxyIp.c_str(), strPort.c_str(), &inAddrInfo, &m_addrinfo) != 0) // error occurs
	{
		throw CException("Error on calling getadrrinfo().");
	}

	if (connect(m_socket, m_addrinfo->ai_addr, m_addrinfo->ai_addrlen))
	{
		throw CException("Error on calling connect().");
	}
}

void CHttpProxy::ConnectServer(std::string ip, unsigned short port)
{
	if (m_socket == INVALID_SOCKET)
	{
		throw CException("Invalid socket fd");
	}
	char tmpBuffer[128] = { 0 };
	::sprintf(tmpBuffer, "CONNECT %s:%d HTTP/1.1\r\nUser-Agent: Mozilla/4.0\r\nConnection: Keep-Alive\r\n\r\n", ip.c_str(), port);
	Send(tmpBuffer, strlen(tmpBuffer));
	Receive(tmpBuffer, sizeof(tmpBuffer));

	int mj, mi, code;
	::sscanf(tmpBuffer, "HTTP/%d.%d %d", &mj, &mi, &code);
	if (code != 200)
	{
		throw CException("http connect emial server faild");
	}
}

int CHttpProxy::Receive(char* buf, int bufLen)
{
	return recv(m_socket, buf, bufLen, 0);
}

bool CHttpProxy::Send(const char* buf, int len)
{
	long ilen = len;
	int sendCnt = 0;
	int ret;

	while (sendCnt < ilen)
	{
		if ((ret = send(m_socket, buf + sendCnt, ilen - sendCnt, 0)) == INVALID_SOCKET)
		{
			return false;
		}
		else
		{
			sendCnt += ret;
		}
	}

	return true;
}
相关推荐
春风解人意1 小时前
从零开始学习嵌入式P32----网络基础之TCP
c语言·网络·学习·tcp/ip
云絮.2 小时前
网络原理---- 网络层,数据链路层,应用层
网络
Johny_Zhao4 小时前
网络安全等级保护测评实施方案
linux·网络·人工智能·网络安全·信息安全·云计算·等保测评·系统运维·itsm
虹科网络安全5 小时前
使用艾体宝 IOTA 10 CORE+ 监控企业网络中的 AI 流量
网络·人工智能
醉颜凉6 小时前
网络安全必学:粘性MAC地址(Sticky MAC)原理与应用全解析
运维·服务器·网络·安全·web安全
广州灵眸科技有限公司7 小时前
从手动三步到上电即连:4G模组systemd开机自连方案
linux·运维·服务器·开发语言·网络·人工智能·php
埃科光电7 小时前
16K万兆网口彩色线阵相机:四倍带宽 高速真彩检测新方案
网络·图像处理·数码相机·计算机视觉·制造·相机
运维全栈笔记8 小时前
Windows 安装 WSL2 并运行 Ubuntu 24.04 指南
linux·网络·windows·ubuntu
qq_452396239 小时前
第十篇:《eBPF 可观测性:零侵扰的深度内核追踪》
服务器·网络·php
迪康Defender9 小时前
政企内网终端安全建设:资产‑管控‑防护‑审计闭环能力拆解
运维·网络·安全·web安全·终端安全管理