当前位置: 首页 > news >正文

HTTP 代理原理及实现(二)

在上篇《HTTP 代理原理及实现(一)》里,我介绍了 HTTP 代理的两种形式,并用 Node.js 实现了一个可用的普通 / 隧道代理。普通代理可以用来承载 HTTP 流量;隧道代理可以用来承载任何 TCP 流量,包括 HTTP 和 HTTPS。今天这篇文章介绍剩余部分:如何将浏览器与代理之间的流量传输升级为 HTTPS。

上篇文章中实现的代理,是一个标准的 HTTP 服务,针对浏览器的普通请求和 CONNECT 请求,进行不同的处理。Node.js 为创建 HTTP 或 HTTPS Server 提供了高度一致的接口,要将 HTTP 服务升级为 HTTPS 特别方便,只有一点点准备工作要做。

我们知道 TLS 有三大功能:内容加密、身份认证和数据完整性。其中内容加密依赖于密钥协商机制;数据完整性依赖于 MAC(Message authentication code)校验机制;而身份认证则依赖于证书认证机制。一般操作系统或浏览器会维护一个受信任根证书列表,包含在列表之中的证书,或者由列表中的证书签发的证书都会被客户端信任。

提供 HTTPS 服务的证书可以自己生成,然后手动加入到系统根证书列表中。但是对外提供服务的 HTTPS 网站,不可能要求每个用户都手动导入你的证书,所以更常见的做法是向 CA(Certificate Authority,证书颁发机构)申请。根据证书的不同级别,CA 会进行不同级别的验证,验证通过后 CA 会用他们的证书签发网站证书,这个过程通常是收费的(有免费的证书,最近免费的 Let's Encrypt 也很火,这里不多介绍)。由于 CA 使用的证书都是由广泛内置在各系统中的根证书签发,所以从 CA 获得的网站证书会被绝大部分客户端信任。

通过 CA 申请证书很简单,本文为了方便演示,采用自己签发证书的偷懒办法。现在广泛使用的证书是 x509.v3 格式,使用以下命令可以创建:

openssl genrsa -out private.pem 2048
openssl req -new -x509 -key private.pem -out public.crt -days 99999

第二行命令运行后,需要填写一些证书信息。需要注意的是 Common Name 一定要填写后续提供 HTTPS 服务的域名或 IP。例如你打算在本地测试,Common Name 可以填写 127.0.0.1。证书创建好之后,再将 public.crt 添加到系统受信任根证书列表中。为了确保添加成功,可以用浏览器验证一下:

fake_certificate

接着,可以改造之前的 Node.js 代码了,需要改动的地方不多:

JSvar http = require('http');
var https = require('https');
var fs = require('fs');
var net = require('net');
var url = require('url');function request(cReq, cRes) {var u = url.parse(cReq.url);var options = {hostname : u.hostname, port     : u.port || 80,path     : u.path,       method     : cReq.method,headers     : cReq.headers};var pReq = http.request(options, function(pRes) {cRes.writeHead(pRes.statusCode, pRes.headers);pRes.pipe(cRes);}).on('error', function(e) {cRes.end();});cReq.pipe(pReq);
}function connect(cReq, cSock) {var u = url.parse('http://' + cReq.url);var pSock = net.connect(u.port, u.hostname, function() {cSock.write('HTTP/1.1 200 Connection Established\r\n\r\n');pSock.pipe(cSock);}).on('error', function(e) {cSock.end();});cSock.pipe(pSock);
}var options = {key: fs.readFileSync('./private.pem'),cert: fs.readFileSync('./public.crt')
};https.createServer(options).on('request', request).on('connect', connect).listen(8888, '0.0.0.0');

可以看到,除了将 http.createServer 换成 https.createServer,增加证书相关配置之外,这段代码没有任何改变。这也是引入 TLS 层的妙处,应用层不需要任何改动,就能获得诸多安全特性。

运行服务后,只需要将浏览器的代理设置为 HTTPS 127.0.0.1:8888 即可,功能照旧。这样改造,只是将浏览器到代理之间的流量升级为了 HTTPS,代理自身逻辑、与服务端的通讯方式,都没有任何变化。

最后,还是写段 Node.js 代码验证下这个 HTTPS 代理服务:

JSvar https = require('https');var options = {hostname : '127.0.0.1',port     : 8888,path     : 'imququ.com:80',method     : 'CONNECT'
};//禁用证书验证,不然自签名的证书无法建立 TLS 连接
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";var req = https.request(options);req.on('connect', function(res, socket) {socket.write('GET / HTTP/1.1\r\n' +'Host: imququ.com\r\n' +'Connection: Close\r\n' +'\r\n');socket.on('data', function(chunk) {console.log(chunk.toString());});socket.on('end', function() {console.log('socket end.');});
});req.end();

这段代码和上篇文章最后那段的区别只是 http.request 换成了 https.request,运行结果完全一样,这里就不贴了。本文所有代码可以从这个仓库获得:proxy-demo。

本文就写到这里,大家有什么问题欢迎给我评论留言。

本文链接:HTTP 代理原理及实现(二) | JerryQu 的小站,参与评论 »

相关文章:

HTTP 代理原理及实现(二)

在上篇《HTTP 代理原理及实现(一)》里,我介绍了 HTTP 代理的两种形式,并用 Node.js 实现了一个可用的普通 / 隧道代理。普通代理可以用来承载 HTTP 流量;隧道代理可以用来承载任何 TCP 流量,包括 HTTP 和 H…...

JavaScript 地址信息与页面跳转

在JavaScript中,你可以使用各种方法来处理地址信息并进行页面跳转。以下是一些常见的方法: 1.使用window.location对象: window.location对象包含了当前窗口的URL信息,并且可以用来进行页面跳转。 * 获取URL的某一部分&#xf…...

力扣(leetcode)第383题赎金信(Python)

383.赎金信 题目链接:383.赎金信 给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。 如果可以,返回 true ;否则返回 false 。 magazine 中的每个字符只能在 ransomNote…...

提升网络安全重要要素IP地址

在数字化时代,网络安全已经成为人们关注的焦点。本文将深入探讨网络安全与IP地址之间的紧密联系,以及IP地址在构建数字世界的前沿堡垒中的关键作用。 网络安全是当今数字社会中不可忽视的挑战之一。而IP地址,作为互联网通信的基础协议&#…...

解析c++空指针解引用奔溃

空指针解引用引起程序奔溃是c/c中最常见的稳定性错误之一。 显然并非所有使用空指针的语句都会导致奔溃,那什么情况下使用空指针才会引起程序奔溃呢?有一个判断标准:判断空指针是否会导致访问非法内存的情况,如果会导致访问非法内…...

Oracle START WITH 递归语句的使用方法及示例

Oracle数据库中的START WITH语句经常与CONNECT BY子句一起使用,以实现对层次型数据的查询。这种查询模式非常适用于处理具有父子关系的数据,如组织结构、分类信息等。 理解START WITH和CONNECT BY 在层次型查询中,START WITH定义了层次结构…...

使用Windbg动态调试目标进程的一般步骤详解

目录 1、概述 2、将Windbg附加到已经启动起来的目标进程上,或者用Windbg启动目标程序 2.1、将Windbg附加到已经启动起来的目标进程上 2.2、用Windbg启动目标程序 2.3、Windbg关联到目标进程上会中断下来,输入g命令将该中断跳过去 3、分析实例说明 …...

Linux驱动学习—输入子系统

1、什么是输入子系统? 输入子系统是Linux专门做的一套框架来处理输入事件的,像鼠标,键盘,触摸屏这些都是输入设备,但是这邪恶输入设备的类型又都不是一样的,所以为了统一这些输入设备驱动标准应运而生的。…...

计算机网络(2)

计算机网络(2) 小程一言专栏链接: [link](http://t.csdnimg.cn/ZUTXU) 计算机网络和因特网(2)分组交换网中的时延、丢包和吞吐量时延丢包吞吐量总结 协议层次及其服务模型模型类型OSI模型分析TCP/IP模型分析 追溯历史 小程一言 我…...

什么是预训练Pre-training—— AIGC必备知识点,您get了吗?

Look!👀我们的大模型商业化落地产品📖更多AI资讯请👉🏾关注Free三天集训营助教在线为您火热答疑👩🏼‍🏫 随着人工智能(AI)不断重塑我们的世界,其发展的一个关键方面已经…...

bat脚本sqlserver 不同数据库同步

如果你想使用批处理脚本(.bat)在 SQL Server 中同步不同数据库的数据,你可以考虑以下步骤: 设置环境变量: 确保你的系统环境变量中已经设置了 SQLCMD 和 BCP 的路径。 编写批处理脚本: 使用 sqlcmd 来执行…...

阶段十-分布式-Redis02

第一章 Redis 事务 1.1 节 数据库事务复习 数据库事务的四大特性 A:Atomic ,原子性,将所以SQL作为原子工作单元执行,要么全部执行,要么全部不执行;C:Consistent,一致性&#xff0…...

微信小程序实战-02翻页时钟-2

微信小程序实战系列 《微信小程序实战-01翻页时钟-1》 文章目录 微信小程序实战系列前言计时功能实现clock.wxmlclock.wxssclock.js 运行效果总结 前言 接着《微信小程序实战-01翻页时钟-1》,继续完成“6个页面的静态渲染和计时”功能。 计时功能实现 clock.wxm…...

每天刷两道题——第十一天

1.1滑动窗口最大值 给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。返回滑动窗口中的最大值 。 输入:nums [1,3,-1,-3,5,3,6,7], k 3 输出&…...

Git提交规范

一. 修改类型 每个类型值都表示了不同的含义,类型值必须是以下的其中一个: feat:提交新功能fix:修复了bugdocs:只修改了文档style:调整代码格式,未修改代码逻辑(比如修改空格、格式…...

apache2的虚拟主机的配置

APACHE2的虚拟主机配置 本章中心概括: 虚拟web主机的初步认识,在redhat系列系统中如何配置,在Debian系列系统中如何配置。 什么是apache2虚拟主机: 简单点讲,就是在同一个物理机中配置多个虚拟主机,从而达…...

Provide/Inject 依赖注入(未完待续)

父组件传递给子组件数据,通过props,但是需要逐层传递 provide/Inject 的推出就是为了解决这个问题,它提供了一种组件之间共享此类值的方式,不必通过组件树每层级显示地传递props 目的是为了共享那些被 认为对于一个组件树而言是全局的数据 p…...

力扣173. 二叉搜索树迭代器

深度优先搜索 思路: 遍历二叉搜索树,左子树总比根节点小,右子树总比根节点大;先深度遍历左子树,然后返回其父节点,然后遍历其右子树节点;使用栈数据结构存储节点数据,借用其“后进先…...

电脑找不到d3dcompiler43.dll怎么修复,教你5个可靠的方法

d3dcompiler43.dll是Windows操作系统中的一个重要动态链接库文件,主要负责Direct3D编译器的相关功能。如果“d3dcompiler43.dll丢失”通常会导致游戏无法正常运行或者程序崩溃。为了解决这个问题,我整理了以下五个解决方法,希望能帮助到遇到相…...

5.3 Android BCC环境搭建(eadb版 上)

写在前面 eadb即eBPF Android Debug Bridge,它是基于adeb的重构。后者曾随aosp 10发布在platform/external目录下。 一,root权限 这里再HighLight下,当前整个专栏都是基于开发环境来展开的,也就是Android设备需要具有root权限。因此该专栏下每一篇博客都是默认了当前开发…...

【Oracle APEX开发小技巧12】

有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...

R语言AI模型部署方案:精准离线运行详解

R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

Element Plus 表单(el-form)中关于正整数输入的校验规则

目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入&#xff08;联动&#xff09;2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...

打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用

一、方案背景​ 在现代生产与生活场景中&#xff0c;如工厂高危作业区、医院手术室、公共场景等&#xff0c;人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式&#xff0c;存在效率低、覆盖面不足、判断主观性强等问题&#xff0c;难以满足对人员打手机行为精…...

【FTP】ftp文件传输会丢包吗?批量几百个文件传输,有一些文件没有传输完整,如何解决?

FTP&#xff08;File Transfer Protocol&#xff09;本身是一个基于 TCP 的协议&#xff0c;理论上不会丢包。但 FTP 文件传输过程中仍可能出现文件不完整、丢失或损坏的情况&#xff0c;主要原因包括&#xff1a; ✅ 一、FTP传输可能“丢包”或文件不完整的原因 原因描述网络…...

Neko虚拟浏览器远程协作方案:Docker+内网穿透技术部署实践

前言&#xff1a;本文将向开发者介绍一款创新性协作工具——Neko虚拟浏览器。在数字化协作场景中&#xff0c;跨地域的团队常需面对实时共享屏幕、协同编辑文档等需求。通过本指南&#xff0c;你将掌握在Ubuntu系统中使用容器化技术部署该工具的具体方案&#xff0c;并结合内网…...

跨平台商品数据接口的标准化与规范化发展路径:淘宝京东拼多多的最新实践

在电商行业蓬勃发展的当下&#xff0c;多平台运营已成为众多商家的必然选择。然而&#xff0c;不同电商平台在商品数据接口方面存在差异&#xff0c;导致商家在跨平台运营时面临诸多挑战&#xff0c;如数据对接困难、运营效率低下、用户体验不一致等。跨平台商品数据接口的标准…...

React父子组件通信:Props怎么用?如何从父组件向子组件传递数据?

系列回顾&#xff1a; 在上一篇《React核心概念&#xff1a;State是什么&#xff1f;》中&#xff0c;我们学习了如何使用useState让一个组件拥有自己的内部数据&#xff08;State&#xff09;&#xff0c;并通过一个计数器案例&#xff0c;实现了组件的自我更新。这很棒&#…...

大数据驱动企业决策智能化的路径与实践

&#x1f4dd;个人主页&#x1f339;&#xff1a;慌ZHANG-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 一、引言&#xff1a;数据驱动的企业竞争力重构 在这个瞬息万变的商业时代&#xff0c;“快者胜”的竞争逻辑愈发明显。企业如何在复杂环…...