Http代理穿透

Stella981
• 阅读 473

原理

HTTP代理服务器中能够提供一种HTTP CONNECT代理服务,能够允许用户建立TCP连接到任何端口。通过CONNECT方法穿透代理的实现方法为:
CONNECT代理服务器的代理端口(如:8080);如果成功返回就可以按照正常的Socket进行通讯。当然在此之前需要先获得代理相关的信息。
如何获取HTTP代理相关信息
程序中是通过读取注册表来获取计算机HTTP代理相关信息的,在注册表的\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings键值下就保存着HTTP代理服务器及端口等信息,
根据该键值下的ProxyEnable值可以判断是否有HTTP代理,没有代理的情况下ProxyEnable值为0。
当然一般情况下程序去中访问该键值可能是受限的,所有就需要获取到访问令牌不受限制的UserSid,使用该UserSid去读取HTTP代理信息。

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));

实现

头文件

#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;
};

实现

#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;
}
点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Stella981 Stella981
2年前
HTTP、HTTPS常用的默认端口号
端口号标识了一个主机上进行通信的不同的应用程序。1.HTTP协议代理服务器常用端口号:80/8080/3128/8081/90982.SOCKS代理协议服务器常用端口号:10803.FTP(文件传输)协议代理服务器常用端口号:214.Telnet(远程登录)协议代理服务器常用端口号:23HTTP服务器,默认端口号为80/tcp(木马Exe
Stella981 Stella981
2年前
Nginx是什么及作用?
一:介绍nginx是一个高性能的HTTP和反向代理服务器,其特点是占用内存少,并发能力强。二:名词介绍代理服务器:代理服务器英文全称是ProxyServer,其功能就是代理网络用户去取得网络信息。形象的说:它是网络信息的中转站,去获取信息。主要的功能有:1.突破自身IP访问限制,访问国外站点。教育网、169网等
Stella981 Stella981
2年前
OkHttp3中的代理与路由
路由是什么呢?路由即是网络数据包在网络中的传输路径,或者说数据包在传输过程中所经过的网络节点,比如路由器,代理服务器之类的。那像OkHttp3这样的网络库对于数据包的路由需要做些什么事呢?用户可以为终端设置代理服务器,HTTP/HTTPS代理或SOCK代理。OkHttp3中的路由相关逻辑,需要从系统中获取用户设置的代理服务器的地址,将HTTP请求转换为代
流浪剑客 流浪剑客
9个月前
Proxifier for Mac (socks5全局代理客户端)
是一款好用的全局代理客户端,它可以让应用程序通过代理服务器连接到互联网。它的主要特点包括:支持各种协议:Proxifier支持HTTP、HTTps、SOCKSv4和v5代理协议,能够满足不同用户的代理需求。灵活配置规则:用户可以根据自己的需要设置代理规则,
公孙晃 公孙晃
6个月前
Proxifier for Mac密钥注册激活版 附完整安装激活教程 支持M1
是一款好用的全局代理客户端,它可以让应用程序通过代理服务器连接到互联网。它的主要特点包括:支持各种协议:Proxifier支持HTTP、HTTps、SOCKSv4和v5代理协议,能够满足不同用户的代理需求。灵活配置规则:用户可以根据自己的需要设置代理规则,
绣鸾 绣鸾
6个月前
Proxifier 3 for Mac全局代理客户端
是一款好用的全局代理客户端,它可以让应用程序通过代理服务器连接到互联网。它的主要特点包括:支持各种协议:Proxifier支持HTTP、HTTps、SOCKSv4和v5代理协议,能够满足不同用户的代理需求。灵活配置规则:用户可以根据自己的需要设置代理规则,
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这