`
xitong
  • 浏览: 6188252 次
文章分类
社区版块
存档分类
最新评论

将stunnel修改成一个透明代理--附:setjmp/longjmp

 
阅读更多

stunnel的代码很简单,简单得没法形容,其执行过程分为下面几个部分:
1.main-loop:
while(1) {
fd = accept
do_client--可应用一些mpm
}
2.do_client:
if(server) {
init_ssl
init_remote
} else if (client) {
init_remote
init_ssl
}
transfer
3.init_ssl:
SSL_new
if(server) {
SSL_accept
} else if (client) {
SSL_connect
}
4.init_remote:
if (server) {
connect-real-server
连接真实的服务器
} else if (client) {
fd作为和用户通信的套接字
}
5.transfer:
while (没有关闭连接){
调用poll或者selece或者epoll等循环将数据从socket中读取然后写入SSL,以及从SSL中读取然后写入socket,实现透明数据转发
}
以上就是stunnel的工作流程,stunnel总是将自己作为client,在stunnel的客户端,它将自己作为stunnel客户端,在stuunel服务器,它将自己作为真实服务器的客户端,这样是很合理的,因为作为代理,它的意义将数据发送给最终的服务,并且向用户转发服务的响应,代理和转发过程中,通过修改stuunel的代码可以实现一个简单的七层过滤功能,不管是stunnel客户端还是stunnel服务器,在代理意义上,前面总是有stunnel的目的地,stunnel始终都是主动地去连接别的主机,即使stunnel服务器会接受stunnel客户端的连接,但是这无非只是为了建立一条安全的应用层隧道,和真正的业务数据无关。
按照stunnel的手册做,很容易使用stunnel配置一个反向代理服务器,诸如下面的配置文件:
server:
...
[https]
accept = 443
connect = 80
client:
...
[https]
accept = 448
connect = 443
这样在用户浏览器中配置stunnel客户端的448端口为代理服务器,所有的80端口的访问全部由stunnel来代理,这就是不透明的隧道式反向代理,所谓不透明是因为需要对用户浏览器进行配置,所谓反向代理是因为真正的目的地址完全由代理服务器决定,所谓隧道式指的是代理服务器并不是直接转发请求,而是分为了c-s模式,c-s之间建立一条安全隧道,这样比较适用于远程代理或者vpn等环境,同时也便于卸载用户环境的代理压力,可以将代理请求本身发往处理能力很强的远端stunnel服务器,本地的代理只需要接收代理请求并转发即可。
可是stunnel无法实现正向代理,因为对于http的正向代理需要解析http请求的头,而这个协议头是应用层数据,stunnel中并没有解析数据,只是透明地转发(详细情况参考transfer函数),因此如果想实现正向http代理则必须对stunnel代码进行一些修改,也就是解析stunnel服务器接收到的第一个请求包,从GET中解析出真实的地址信息后,然后再决定如何转发,这就涉及到了http协议,本文不谈。即使对http的正向代理实现了,那么对其它基于tcp协议的应用的正向代理如何实现呢?这就需要stunnel知道客户端需要访问的真实地址信息,因此这种代理很大程度上也就是透明代理,通过设置路由或者在windows上通过spi的方式将客户端对tcp应用的访问以stunnel客户端为下一跳,当请求过来后,通过下面的配置将请求重定向到stunnel客户端:
iptables -t nat -A PREROUTING --protocol tcp -m tcp -j REDIRECT --to-port xxx
xxx为stunnel客户端监听的端口。如此一来所有的请求都被定向到了stunnel,下面的问题是如何能得到这些请求原始的目的地信息,如果你很精通nat原理以及linux的实现,那么这个问题很简单,直接通过下面的调用就能得到:
getsockopt (fd, SOL_IP, SO_ORIGINAL_DST, &addr, &size);
得到了这个原始地址信息之后,需要想办法将之传给stunnel服务器,这样stunnel服务器才能根据这个地址信息来决定如何做,这时stunnel并不需要进行类似反向代理那样的配置。我们可以自定义一个通道将这个信息传过去,可是那样实现很松散,必须考虑连接和这个原始地址信息的对应关系,因此不用。由于stunnel客户端和stunnel服务器之间是一个ssl连接,在RFC5246中对ssl协议进行了更新,client-hello消息如下:
struct {
ProtocolVersion client_version;
Random random;
SessionID session_id;
CipherSuite cipher_suites<2..2^16-2>;
CompressionMethod compression_methods<1..2^8-1>;
select (extensions_present) {
case false:
struct {};
case true: //多了一个extension字段
Extension extensions<0..2^16-1>;
};
} ClientHello;
因此完全可以将这个地址信息通过这个client-hello消息的extension传给stunnel服务器,由于OpenSSL本身并没有将特性导出接口,故而需要对OpenSSL代码进行修改,本文省略。在stunnel服务器端,可以从这个hello消息中将该原始地址信息解析出来,然后以此信息进行连接决策。到此为止,整套的解决方案已经有了,下面就是如何修改代码的问题了。过程如下:
第一步:配置上述的nat规则;
第二步:其次修改prototypes.h中的CLI结构体,添加几个字段,并且添加相应的结构体定义:
typedef struct {
union {
struct sockaddr_in addr;
char szAddr[16];
char szPort[6];
} addr; //传输hello消息时,最好将信息编码为字符串,但是使用它进行connect的时候还是需要转化为sockaddr_in
char ext[0];
}ORIG_ADDR;
typedef struct {
...
} REAL_ADDR_CTX;
typedef struct {
...
ORIG_ADDR orig; //原始地址信息
REAL_ADDR_CTX orig_ctx; //ssl中和hello-extension相关的结构体
} CLI;
第三步:修改alloc_client_session,增加:
if (opt->option.client) {
int err = 1;
socklen_t sin_size = sizeof(struct sockaddr_in);
err = getsockopt (rfd, SOL_IP, SO_ORIGINAL_DST, &c->orig.addr, &sin_size);
...
//为c->orig.addr赋值,转化为字符串格式
}
第四步:修改init_ssl函数,服务器和客户端添加的代码不同:
1.SSL_new之后:
if (c->opt->option.client){
//对于client,用用户的真实目的地址信息初始化CLI的orig_ctx字段,也就是将之填入ssl相关的结构体,SSL_connect的时候会通过client-hello发送
} else {
//对于server,准备好CLI的orig_ctx字段,准备在SSL_accept之后接收用户的原始地址信息
}
2.SSL_accept(c->ssl)之后(肯定是server的情况):
取出client-hello-extension的消息,初始化CLI的orig_ctx结构体
第五步:修改connect_remote函数,初始化连接地址结构体前添加:
if(!c->opt->option.client){ //仅仅在server端添加
ret = callback(...);//在callback中可以根据策略修改最终的地址,也就是修改c->orig.addr.addr
memcpy(&addr.sa, &c->orig.addr.addr, sizeof addr);
}
以上五个步骤做完,stunnel也就成了一个透明代理了,用户无需在本地做任何配置(当然需要将网关设置为stunnel客户端,在windows上还可以利用spi),stunnel作为透明代理就转发了你的tcp请求(可能还会冲定向或者拦截),当然还可以进一步修改,使一切可配置化,不过这就和框架原理没有关系了。
附:setjmp和longjmp
stunnel使用setjmp来安装错误处理代码,这一点感觉很好,比如在一个连接刚建立并且处理业务之前,即run_client的开头,有如下调用:
static void run_client(CLI *c) {
...
error=setjmp(c->err);
if(!error) //直接调用setjmp,其返回为0,如果是从longjmp中返回的setjmp,其返回为1
do_client(c); //直接调用setjmp相当于仅仅安装错误处理代码,do_client完整的实现了业务逻辑,调用层次很深。
//如果do_client中以及其调用过程中的某处出现错误,就会调用longjmp(c->err),然后执行绪到达上面setjmp处,返回1,此时就要真正处理错误了,下面的代码全部是错误处理
s_log(...); //日志记录
...//资源清理后返回,结束此次连接
}
需要注意的是,虽然longjmp可以使得执行绪跳转到setjmp处,但是由于jmp_buf是基于当前栈帧的,因此必须在比setjmp调用层次更深的地方调用longjmp,也就是说setjmp的调用函数不能返回,返回了,longjmp就失效了,之所以有的情况下setjmp返回了longjmp还可用,那是因为栈虽然清了,为了效率只是改写了esp,ebp等寄存器的值,栈上的数据依然存在,因此longjmp恢复setjmp的jmp_buf时,数据依然是存在的,但是已经不可用了。因此一般的做法是,在处理的开始处调用setjmp安装错误处理代码,然后在该栈帧不返回前提下,后续的代码出错后调用longjmp。

分享到:
评论

相关推荐

    2024-2030全球与中国盐氯化系统市场现状及未来发展趋势.docx

    2024-2030全球与中国盐氯化系统市场现状及未来发展趋势

    基于深度学习的积灰检测识别-图像分类源码+数据集.zip

    详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;

    沈阳药科大学-答辩通用PPT模板我给母校送模板作品.pptx

    PPT模板,答辩PPT模板,毕业答辩,学术汇报,母校模板,我给母校送模板作品,周会汇报,开题答辩,教育主题模板下载。PPT素材下载。

    微信备忘录小程序源码 作业设计demo 计算机专业作业

    微信备忘录小程序源码 作业设计demo 微信备忘录小程序是一种便捷的个人记事应用,它允许用户在微信内快速记录和查看备忘录。以下是对微信备忘录小程序的简要介绍: --- **微信备忘录小程序** 微信备忘录小程序为用户提供了一个简单、直观的记事平台。用户可以通过这个小程序记录日常事务、重要提醒和个人笔记,非常适合忙碌的现代生活节奏。 主要特点包括: 1. **快速记录**:用户可以迅速添加文本、列表或语音备忘录。 2. **定时提醒**:为每个备忘录设置提醒时间,确保不会错过任何重要事项。 3. **个性化分类**:支持自定义分类,便于管理和查找备忘录。 4. **界面友好**:清晰的界面设计,操作简便,无需复杂的学习过程。 5. **数据同步**:通过微信账号登录,实现备忘录的云端同步,方便在不同设备间切换使用。 此外,小程序还具备以下优势: - **隐私保护**:备忘录内容仅对用户本人可见,保障个人隐私。 - **无广告干扰**:提供一个无广告的清爽记事环境。 - **离线存储**:即使在无网络环境下,也能正常使用,记录的内容会在联网后自动同步。 微信备忘录小程序是日

    中国海洋大学-汇报答辩专用PPT模板我给母校送模板作品.pptx

    PPT模板,答辩PPT模板,毕业答辩,学术汇报,母校模板,我给母校送模板作品,周会汇报,开题答辩,教育主题模板下载。PPT素材下载。

    毕业设计:python基于深度学习的交通标志识别系统(源码 + 数据库 + 说明文档) 太多存百度云盘

    毕业设计:python基于深度学习的交通标志识别系统(源码 + 数据库 + 说明文档) 2 开发工具及技术 2 2.1 B/S结构的介绍 2 2.2 PYTHON技术的介绍 2 2.3 HTML技术的介绍 2 2.4 MYSQL数据库的介绍 3 2.5 深度算法的介绍 3 2.6 开发环境的介绍 3 3 需求分析 4 3.1 可行性分析 4 3.2 功能需求分析 4 3.3 非功能需求分析 4 4 总体设计 6 4.1 系统总体结构设计 6 4.2 系统的数据库设计 6 5 系统功能实现 6 5.1 登录及注册 6 5.2 首页展示 6 5.3 个人信息 6 5.4 用户管理 6 5.5 修改密码 6 5.6 图片识别 6 5.7 摄像头识别 6 5.8 天气识别 6 6 系统测试 6 6.1 测试目的 6 6.2 测试内容 6 6.3 测试总结 6

    083ssm-vue汉服文化平台网站.zip(可运行源码+数据库文件+文档)

    本L文主要论述了如何使用JAVA语言开发一个汉服文化平台网站 ,本系统将严格按照软件开发流程进行各个阶段的工作,采用B/S架构,面向对象编程思想进行项目开发。在引言中,作者将论述汉服文化平台网站的当前背景以及系统开发的目的,后续章节将严格按照软件开发流程,对系统进行各个阶段分析设计。 汉服文化平台网站的主要使用者分为管理员和用户,实现功能包括管理员:首页、个人中心、汉服知识管理、服装展示管理、服装类别管理、用户相册管理、论坛交流、系统管理、订单管理,用户:首页、个人中心、用户相册管理、论坛交流、我的收藏管理、订单管理,前台首页;首页、汉服知识、服装展示、用户相册、论坛交流、个人中心、后台管理、购物车、在线客服等功能。由于本网站的功能模块设计比较全面,所以使得整个汉服文化平台网站信息管理的过程得以实现。 本系统的使用可以实现汉服文化平台网站管理的信息化,可以方便管理员进行更加方便快捷的管理,可以提高管理人员的工作效率。 关键词:汉服文化平台网站 JAVA语言;MYSQL数据库;SSM 框架

    HTML5浪漫爱心表白动画在线演示程序

    HTML5浪漫爱心表白动画在线演示程序

    node-v13.12.0-linux-armv7l.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    实验3-关系运算设计(c语言编程).doc

    实验3-关系运算设计(c语言编程).doc

    对京东网站的分析(ppt文档).ppt

    对京东网站的分析(ppt文档).ppt

    C#本科毕业设计基于Unity3D引擎的网络角色扮演游戏设计与实现源代码.zip

    高分设计源码,详情请查看资源内容中使用说明 高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明

    2021数学建模美赛C题代码.zip

    最全的数学建模美赛C题和代码、大量刷题题库、逻辑清晰易于学习

    基于MATLAB的PCA算法人脸识别项目源码+GUI界面+说明文档.zip

    详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;详情请查看资源内容中使用说明;

    上海交通大学-通用PPT模板我给母校送模板作品.pptx

    PPT模板,答辩PPT模板,毕业答辩,学术汇报,母校模板,我给母校送模板作品,周会汇报,开题答辩,教育主题模板下载。PPT素材下载。

    办公自动化(OA)是面向组织的日常运作和管理,员工及管理者使用频率最高的应用系统,极大提高公司的办公效率.zip

    springboot框架 一、Spring Boot基础应用 Spring Boot特征 概念: 约定优于配置,简单来说就是你所期待的配置与约定的配置一致,那么就可以不做任何配置,约定不符合期待时才需要对约定进行替换配置。 特征: 1. SpringBoot Starter:他将常用的依赖分组进行了整合,将其合并到一个依赖中,这样就可以一次性添加到项目的Maven或Gradle构建中。 2,使编码变得简单,SpringBoot采用 JavaConfig的方式对Spring进行配置,并且提供了大量的注解,极大的提高了工作效率,比如@Configuration和@bean注解结合,基于@Configuration完成类扫描,基于@bean注解把返回值注入IOC容器。 3.自动配置:SpringBoot的自动配置特性利用了Spring对条件化配置的支持,合理地推测应用所需的bean并自动化配置他们。 4.使部署变得简单,SpringBoot内置了三种Servlet容器,Tomcat,Jetty,undertow.我们只需要一个Java的运行环境就可以跑SpringBoot的项目了

    市政交通信号工程检验批质量验收记录.doc

    市政交通信号工程检验批质量验收记录.doc

    浙江农林大学-答辩通用PPT模板我给母校送模板作品.pptx

    PPT模板,答辩PPT模板,毕业答辩,学术汇报,母校模板,我给母校送模板作品,周会汇报,开题答辩,教育主题模板下载。PPT素材下载。

    工程监理企业信息化解决方案.doc

    工程监理企业信息化解决方案.doc

    工总承包企业特级资质标准信息化考评表.doc

    工总承包企业特级资质标准信息化考评表.doc

Global site tag (gtag.js) - Google Analytics