HttpTunnel工作原理及源程序分析

http协议解决粘包拆包半包 的编码解码过程、 以及netty 使用http协议的原理 本文主要介绍netty对http协议解析原理,着重讲解keep-alive,gzip,truncked等机制,详细描述了netty如何实现对http解析的高性能。 1 http协议 1.1 描述 标示 ASCII 描述 字符 CR 13 Carriage return (回车) \r LF 10 Line feed character(换行) \n SP 30   Horizontal space(... 阅读详情
这份报告对开源工程HttpTunnel的工作原理及源程序运行流程进行分析,重点分析HttpTunnel对HTTP协议的封装与实现。
1 工作原理概述
         HttpTunnel通过HTTP请求方式,提供了一个双向的、虚拟的数据通路,可以通过http proxy来使用(不是必需)。
         HttpTunnel编译连接之后得到两个可执行的文件,hts和htc,hts是服务器端程序,用于要连接的外部主机之上,htc是客户端程序,用于本地主机之上。这两个部分连接用于产生一个虚拟的数据通道(tunnel)。
         Http Tunnel利用HTPP的POST与GET两个命令建立了两个连接,分别用于客户端向服务器发送和接收数据,而且考虑到了HTTP数据的合法性,会随时检查所接收或发出的数据是否超过content-length规定的长度,如果是则填充完后重新开连接进行处理新的数据,保证了数据始终是合法的HTTP数据,完全等价于客户端在同时用HTTP协议在上传和下载一个大文件,文件数据中不需要任何的HTTP命令或HTML语言标记。
2 HttpTunnel程序流程分析
2.1 服务器端程序流程分析
hts是服务器端,安装在外部网络一侧,也就是没有防火墙的一端。
hts源文件包括hts.c, common.c, tunnel.c, http.c这几个文件和port目录下的库。
流程如下:
main() (hts.c)
         parse_arguments (argc, argv, &arg),解析命令行参数;
         调用tunnel = tunnel_new_server (arg.port, arg.content_length)创建新的tunnel的服务端;
       初始化tunnel, in_fd, out_fd都为-1
       在tunnel->server_socket监听 server_socket (tunnel->dest.host_port, 1), backlog=1, 注意用了SO_REUSEADDR选项;                                              àcommon.c
         通道的一些选项:strict_content_length, keep_alive, max_connection_age, 这些在HTTP头说明中会用到;  
         写PID文件
         进入无限循环
如果定义输入输出的终端设备(arg.device),打开设备fd = open_device (arg.device),common.c;
       tunnel_accept接受外部连接                                          àtunnel.c
       accept()连接
      解析HTTP协议请求数据: http_parse_request (s, &request),                   http.c
       POST或PUT命令, 将此socket设置为tunnel的in_fd, 用于接收客户端的数据;
       GET命令, 将此socket设置为tunnel的out_fd, 用于发送去往客户端的数据;
       如果设置了转发端口(arg.forward_port != -1), 调用do_connect连接到这个端口,描述符为fd, 注意这个连接是本机的
      自己连自己的内部连接, hts起到代理转发作用, 目标端口也就是真正的被HTTP包裹的协议端口;
        进入下一个循环
      poll: fd 和tunnel->server_socket, 也就是网络通道数据和内部连接数据对倒;
        handle_input()
       handle_device_input()处理fd输入信息;                                common.c
       handle_input()
       handle_tunnel_input()处理来自通道的信息;                            common.c
服务器端接收了客户端的两个连接, POST命令对应的连接服务器接收数据, GET命令对应的连接服务器发送数据。
2.2 客户端程序流程分析
htc是客户端,安装在防火墙内部网络一侧,也即客户浏览器一端。
htc源文件包括htc.c, common.c, tunnel.c, http.c, base64.c这几个文件和port目录下的库程序
流程如下:
main.c (htc.c)
         parse_arguments (argc, argv, &arg); 解析命令行参数,                        àhtc.c
如果转发端口 (arg.forward_port != -1),在此端口打开socket监听 s = server_socket
(arg.forward_port, 0),                            
      backlog=0, 其实不收连接, 注意用了SO_REUSEADDR选项,               àcommon.c
         进入无限循环 for (;;);
       定义输入输出的终端设备(arg.device),打开设备fd = open_device (arg.device),common.c;   
否则如果定义了转发端口(arg.forward_port != -1),输入输出通过连接的socket来进行fd = wait_for_connection_on_socket (s),就是accept() ,                               à htc.c
打开一个新的通道  tunnel = tunnel_new_client (arg.host_name, arg.host_port,
      arg.proxy_name, arg.proxy_port,
      arg.content_length); tunnel.c
       注意tunnel结构中的in_fd, out_fd都初始化为-1,表示没有连接, 缺省的content_length是100K字节.            
设置通道的一些选项:strict_content_length, keep_alive, max_connection_age, user_agent这些在HTTP头说明中会用到, 支持代理;              
如果要进行代理认证(arg.proxy_authorization != NULL),将认证参数进行base64编码,作为通道的proxy_authorization参数;
通道连接对方tunnel_connect (tunnel), tunnel.c, 建立http tunnel,主要是调用函数tunnel_write_request (tunnel, TUNNEL_OPEN, auth_data, sizeof auth_data)
 如果要写入和已经写入的数据长度超过content_length, 对tuenel进行填充;
       对于客户端已经连接好的tunnel,超时时进行断开;
       对于断开(或第一次连接)的客户端, 调用tunnel_out_connect (tunnel)发起连接
       调用do_connect()连接服务器(第一个连接), socket描述符为tunnel->out_fd.
       设置该socket的一些选项;
       调用shutdown(out_fd, 0), 不接收数据;
       调用http_post()函数向服务器发送HTTP的POST命令; http.c      
调用tunnel_write_data (tunnel, &request, sizeof request)函数向服务器写要执行的请求(此时为TUNNEL_OPEN)
       继续写data部分,先写长度,然后是数据(此时为dummy的auth_data=42, length=1),(即HTTP的POST命令向服务器写TUNNEL_OPEN命令和一个dummy数据),然后进行数据长度判断是否在此连接中数据写多了.
      进入函数tunnel_in_connect (tunnel) , 数据进入的连接
调用do_connect()连接服务器(第2个连接),socket描述符为tunnel->in_fd.
设置该socket的一些选项;
      调用http_get()函数向服务器发送HTTP的GET命令;                      à http.c
      调用shutdown(in_fd, 1), 不再写数据;
      调用http_parse_response (tunnel->in_fd, &response)解析HTTP服务器返回数据;
      处理统计信息
       此时tunnel_connect完成
       进入下一个循环
      poll选择用户的输入设备fd和网络tunnel的in_fd(第2条连接)数据,也就是用户的输入信息和服务器返回的信息进行对倒:
       fd输入->tunnel->out_fd输出; tunnel->in_fd输入->fd输出.
      handle_input()
       handle_device_input()处理用户输入信息,                             àcommon.c
       handle_input()
       handle_tunnel_input()处理来自通道的信息,                           àcommon.c
客户端一共向服务器发起了两个连接, 第一个连接用于发送数据,第2个连接用于接收数据
3 HttpTunnel源码相关分析
3.1 HTTP头的封装与实现
3.1.1 HTTP头结构
在HttpTunnel中,将HTTP头实现为名值对。是一个递归的结构。
typedef struct http_header Http_header;
struct http_header
{
const char *name;
const char *value;
Http_header *next; /* FIXME: this is ugly; need cons cell. */
};
3.1.2 创建HTTP头
static inline Http_header *
http_alloc_header (const char *name, const char *value)
{
Http_header *header;
header = malloc (sizeof (Http_header));
if (header == NULL)
     return NULL;
header->name = header->value = NULL;
header->name = strdup (name);
header->value = strdup (value);
if (name == NULL || value == NULL)
{
     if (name == NULL)
              free ((char *)name);
     if (value == NULL)
              free ((char *)value);
     free (header);
     return NULL;
}
return header;
}
 
3.1.3 添加HTTP头
Http_header *
http_add_header (Http_header **header, const char *name, const char *value)
{
     Http_header *new_header;
     new_header = http_alloc_header (name, value);
     if (new_header == NULL)
              return NULL;
     new_header->next = NULL;
     while (*header)
              header = &(*header)->next;
     *header = new_header;
     return new_header;
}
tunnel:一款单线程、轻量级和高性能的内网穿透程序,支持TCP流量转发(支持所有TCP上层协议,包括HTTP,SSH等),支持多客户端同时连接 Tunnel Tunnel是一款单线程、轻量级和高性能的内网穿透程序,支持TCP流量转发(支持任何TCP上层协议,包括HTTP,SSH等),支持多客户端同时连接。 解决公网无法访问内部网络服务问题,使内部网络服务能被公网访问。 说明 该项目使用CMake构建,Linux系统编译后会产生两个可执行文件,tunneld(服务器端)和tunnel(客户端),其他系统编译后只会产生tunnel(客户端)。 tunneld考虑性能原因,使用epoll I/O模型,仅支持Linux系统,且Linux内核版本要大于等于2.5.44。 tunnel使用select I/O模型,支持主流系统(Mac OS、Windows、Linux)。 公网映射端口为动态分配,暂时不支持指定端口。 tunneld(服务器端)使用说明 执行 tunneld 文件 $ tunneld $ Enter listening por 立即下载

相关推荐

httptunnel源代码(难得的windows版)

HttpTunnel是一个开源的HTTP隧道实现。利用它能够方便的将自己应用的通讯进行HTTP封装,而不需要对应用作任何修改。是穿透防火墙的利器。现在一般能找到的是linux版本。有人将其移植到了windows平台。

HTTPTunnel-开源

启用通过限制性HTTP代理建立网络连接的隧道。 功能:端口映射,SOCKS4,SOCKS5,基于Web的管理界面,可以使用独立服务器(perl)或托管服务器(PHP),来自LDAP或MySQL的可选授权

Android 13 Hotseat定制化修改——001 hotseat布局方向

一.背景由于需求是需要自定义修改Hotseat,所以此篇文章是记录如何自定义修改hotseat的,应该可以覆盖大部分场景,修改点有修改hotseat布局方向,hotseat图标数量,hotseat图标大小,hotseat布局位置,hotseat图标禁止形成文件夹,hotseat图标禁止移动到Launcher...

Java_fenxiang的博客 1104

VBA解决Excel批处理任务之:批量修改Sheet名称

针对需要批量处理大量的Sheet改名的场景,使用VBA是非常便捷的方式。 简单介绍几种方法: 1. 录制宏法: 录制宏是用Excel自带的工具把改名改成一个可以复制操作的动作。 这里选择录制,会弹出一个宏设置窗口: 这里设置好宏名称就好,然后确定就可以开始录制你的操作。操作完成之后,再进入到宏窗口点击结束录制: 这样就可以通过执行来运行了,运行方法: 1. 通过选择宏: ...

跬步至千里 1万+

CODESYS开发实战:EtherCAT总线伺服从站配置与运动控制

本文详细介绍了在CODESYS平台上进行EtherCAT总线伺服从站配置与运动控制的实战教程。内容涵盖从设备描述文件安装、主从站拓扑构建,到核心的伺服使能状态机编程、过程数据映射,以及最终实现点位运动控制的完整流程。文章旨在帮助开发者快速掌握基于CODESYS的EtherCAT总线伺服控制技术,提升工业自动化项目开发效率。

weixin_29281915的博客 328

华为OD机试 - 统计文本数量(Java 2025 A卷 100分)

华为OD机试 2025A卷题库疯狂收录中,刷题。

学Java,找哪吒 1438

使用Qt和MX Component插件实现与菱PLC的通信

在本文中,我们介绍了如何使用Qt和MX Component插件实现与菱PLC的通信。我们首先安装和配置了MX Component插件,并在Qt项目中初始化和使用MX Component来连接、读取和写入PLC的数据。安装完成后,您需要在Qt项目中配置MX Component的路径,以便Qt可以找到所需的库文件。在本文中,我们将探讨如何使用Qt和MX Component插件来实现与菱PLC的通信。在主函数中,我们将初始化MX Component,并创建一个与PLC通信的示例。在上面的代码中,我们使用了。

TlScratch的博客 996

openssl+SM2开发实例一(含源码)

是中国国家密码管理局(CNCA)颁布的椭圆曲线密码算法标准,属于非对称加密算法。它基于椭圆曲线离散对数问题,提供了安全可靠的数字签名、密钥交换和公钥加密等功能。SM2被设计为适用于各种场景下的密码学应用,包括数字证书、数据加密、数字签名、身份认证等。SM2是一种非对称加密算法,意味着它使用两个密钥:公钥和私钥。公钥用于加密数据和验证签名,而私钥用于解密数据和生成签名。SM2基于椭圆曲线密码学(Elliptic Curve Cryptography,ECC),使用椭圆曲线上的点运算来实现加密和签名操作。

N阶二进制的博客 7990

DSPy 入门: 再见提示,你好编程

DSPy("Declarative Self-improving Language Programs (in Python)",发音为 "dee-es-pie")[1] 是斯坦福大学 NLP 研究人员开发的 "基础模型编程 "框架。它强调编程而非提示,并将构建基于 LM 的管道从操作提示转向编程。因此,它旨在解决构建基于 LM 应用程序时的脆弱性问题。DSPy 还将程序的信息流与每一步的参数(提示和 LM 权重)分离开来,为构建基于 LM 的应用程序提供了更系统的方法。

具身机器人和通用AI 3488

建立时间与保持时间

建立时间与保持时间的计算 文章目录1、建立时间与保持时间概述及模型2、寄存器之间数据传输时建立时间与保持时间3、寄存器之间数据传输时建立时间余量与保持时间余量计算4、 FPGA允许的最大时钟频率或最小时钟周期5、计算FPGA时钟所允许的最大频率或最小时钟周期6、违反建立和保持时间会发生什么? 1、建立时间与保持时间概述及模型 建立时间(Tsu): 在时钟采样之前,输入必须稳定一段时间,该时间量称为建立时间。 理想最优建立时间: 保持时间(Th): 在时钟沿之后输入到触发器稳定所需的最短时间。 理想最优

Crazzy_M的博客 3万+

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

上一篇: Full-Duplex Channel over HTTP
下一篇: HttpTunnel解读和防御
iiprogram
博客等级 码龄25年 1068粉丝 1515原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值