网站怎么做前台跟后台的接口,株洲网络学院,网站建设公司哪家好 该如何选择,济南设计公司排名OpenSSL自签证书并基于Express搭建Web服务进行SSL/TLS协议分析
起因
最近在学习安全协议#xff0c;大多数实验都是基于Windows下IIS#xff0c;或者Linux下nginx搭建的Web服务#xff0c;搭建环境和编写配置文件比较麻烦。而且我有多个不同环境的设备#xff0c;折腾起来…OpenSSL自签证书并基于Express搭建Web服务进行SSL/TLS协议分析
起因
最近在学习安全协议大多数实验都是基于Windows下IIS或者Linux下nginx搭建的Web服务搭建环境和编写配置文件比较麻烦。而且我有多个不同环境的设备折腾起来也比较麻烦最好是开箱即用。
所以我就用nodejs express写了个跨平台的项目专门用于对比没有使用SSL/TLS的http与使用了的https协议。
如果你对代码不感兴趣仅是想要分析协议可以到文章末尾的Github仓库中去下载该项目运行即可。
搭建环境
安装nodejs访问官网https://nodejs.org建议下载LTS版本并安装 node --version
npm --version运行上方命令出现版本号即可。
在终端中运行如下命令安装yarn
npm -g install yarnyarn --version出现版本号即为成功。
另外需要搭建OpenSSL环境这个教程网上有很多请自行搜索。
代码部分
接下来主要分享代码编写思路。
目录结构
创建项目目录为http_ssl并在终端中进入
mkdir http_ssl
cd http_ssl使用yarn初始化按照提示填写或者一路回车即可
yarn init创建静态资源目录、配置文件目录、源码目录
mkdir asset
mkdir config
mkdir src安装依赖
添加express包等
yarn add express在package.json文件中修改type为module将语法为ES6并编写启动命令scripts。如果没有直接添加
type:module,
scripts:{start:node ./src/index.js
}完整文件大致如下
{name: http_ssl,version: 1.0.0,main: index.js,author: cairbin,license: MIT,dependencies: {express: ^4.19.2},type:module,scripts:{start:node ./src/index.js}
}初始文件
我们希望http和https的端口号、主机地址之类的都能够放在配置文件里而非代码中这样方便我们更改于是编写配置文件。
touch config/config.js我们这里为了让配置文件能够像模块一样倒入直接为js后缀编辑该文件
// config/config.js
export default {server:{static: ../asset, //静态资源目录注意../因为index.js在src下否则找不到这个目录http:{host: localhost, //主机地址port: 8848 //端口号},https:{host:localhost,port:8849}}
}创建src/index.js为程序入口我们编写的启动命令就是运行这个文件的
touch src/index.js然后编写一个404.html的静态文件
mkdir asset/html/
touch asset/html/404.html!DOCTYPE html
html langen
headmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0title404 Page/title
/head
bodyh1404 NOT FOUND/h1
/body
/html辅助模块
项目还需要日志功能我们没必要搞太复杂想要功能强大的可以引入winston包我这里就简单封装下js自带的console.*
mkdir src/utils/
touch src/utils/logger.js// src/utils/logger.js
const log (options){console[options.type]([${options.type.toUpperCase()}] ${options.msg})
}const info (msg){log({type:info,msg:msg});
}const warn (msg){log({type:warn,msg:msg});
}const error (msg){log({type:error,msg:msg});
}export default{info,warn,error
}控制器
尽管是个Demo但最好还是遵循MVC我们创建目录和文件编写一个简单控制器
mkdir src/controller/
touch src/controller/defaultController.js// src/controller/defaultController.js
import logger from ./../utils/logger.js; //日志模块const defaultFunc (req, res, next){logger.info(exec defultController.defaultFunc);res.status(500).send(Hello World!); //为了抓包分析方便返回500状态码而非200
}export default{defaultFunc
}这里注意为了抓包方便观察我们返回的Code为500而不是200。
路由
创建Express的路由
mkdir src/route/
touch src/route/defaultRoute.js// src/route/defaultRoute.js
import express from express;
import defaultController from ./../controller/defaultController.js;
import logger from ./../utils/logger.js; //日志模块const router express.Router();router.get(/,(req,res,next){logger.info(defaultRoute, path/);defaultController.defaultFunc(req, res, next);
})export default router;创建服务
创建http和https服务指定静态资源目录设置404页面并集成使用以上编写的文件
// src/index.js
import express from express;
import https from https;
import http from http;
import defaultRoute from ./route/defaultRoute.js
import fs, { copyFile } from fs;
import path from path;
import { dirname } from node:path;
import { fileURLToPath } from node:url
import config from ./../config/config.js;
import logger from ./utils/logger.js;const __filename fileURLToPath(import.meta.url)
const __dirname dirname(__filename)const app express();
const httpsServer https.createServer({key:fs.readFileSync(keys/private.pem),cert:fs.readFileSync(keys/file.crt)
},app)
const httpServer http.createServer({},app);//static path
app.use(express.static(path.join(__dirname, config.server.static)));
logger.info(static file path ${path.join(__dirname, config.server.static)});app.use(/,defaultRoute);
// 404 page
app.use(*,(req,res){res.redirect(./html/404.html)
})httpsServer.listen(config.server.https.port, config.server.https.host, (){logger.info(https service is running on https://${config.server.https.host}:${config.server.https.port});
})httpServer.listen(config.server.http.port, config.server.http.host, (){logger.info(http service is running on http://${config.server.http.host}:${config.server.http.port});
})你会发现keys这个用于存放证书的目录以及证书文件并不存在我们接下来创建它们项目才能运行。
另外需注意上面的静态资源目录用path.join()来设为绝对路径。
生成证书
我们使用OpenSSL自签一个证书在macOS或者Linux下可编写脚本
touch generate.sh# generate.sh
mkdir -p keys
openssl genrsa 4096 keys/private.pem
openssl req -new -key keys/private.pem -out keys/csr.pem
openssl x509 -req -days 365 -in keys/csr.pem -signkey keys/private.pem -out keys/file.crt然后运行脚本
sh generate.sh如果是Windows的话也可以编写.bat批处理文件或者直接执行命令
mkdir keys
openssl genrsa 4096 keys/private.pem
openssl req -new -key keys/private.pem -out keys/csr.pem
openssl x509 -req -days 365 -in keys/csr.pem -signkey keys/private.pem -out keys/file.crt注意旧版本的CMD或PowerShell可能不支持/可以改用\可能需要转义字符\\
运行项目
执行我们编写好的指令(package.json那里的)运行项目
yarn run start正常情况下控制台应该是在报[INFO]
浏览器地址栏输入http://localhost:8848即可看到Hello World!页面最指定协议头有些浏览器会自动填充为https https的话请访问https://localhost:8849正常来讲现代的浏览器会阻止你访问这个页面并提示非私人连接不安全因为我们用的是自签名的证书。 直接无视风险继续访问(doge) 抓包分析
关闭页面在浏览器的设置里清除浏览器缓存这一步很重要因为我们之前访问过页面了浏览器为了加速一般都会有缓存导致下次访问时不是向服务器请求而是加载本地缓存的页面导致抓包失败
启动wireshark并进行抓包与其他情况不同由于是回环地址所以我们要抓loopback的包 先来访问http未加密的页面在wireshark中使用过滤器过滤http的包该项目为了排除抓包的时候的干扰访问页面返回的状态码为500而不是200所以我们只需要找到http status 为500的包即可 查看数据果然是明文 再以https协议的方式访问一次并进行抓包 发现抓不到了我们将过滤器条件改为tls 由此看到数据都被保护起来了即使抓到也都是密文。
Wireshark是直接看到TLS封包的内容的我们可以配置环境变量让浏览器得到的preMasterKey放到指定log中wireshark支持读取这个文件然后再进行抓包就可以查看加密的数据了。
文章可以参考 https://segmentfault.com/a/1190000018746027
代码仓库
Click CairBin/SecurityProtocolLab