网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
OPTARG_DISABLE_PROTOCOL
};
// https server帮助信息
static const char* help =
“Usage %s [opts] :\n”
" -cert : Server PEM-encoded X.509 Certificate file\n"
" -key : Server PEM-encoded Private Key file\n"
" -ca : File of PEM-encoded Server CA Certificates\n"
" -capath
" -ciphers : Accepted SSL Ciphers\n"
" -verify-peer : Enable SSL client verification\n"
" -enforce-peer-cert : Reject clients without a cert\n"
" -verify-depth : Maximum depth of CA Certificates in Client Certificate verification\n"
" -enable-protocol
: Enable one of the following protocols: SSLv2, SSLv3, TLSv1, or ALL\n"
" -disable-protocol
: Disable one of the following protocols: SSLv2, SSLv3, TLSv1, or ALL\n"
" -ctx-timeout : SSL Session Timeout (SSL >= 1.0)\n";
// 获取并解析用户输入的https server参数,配置evhtp的ssl信息
evhtp_ssl_cfg_t parse__ssl_opts_(int argc, char* argv)
{
int opt = 0;
int long_index = 0;
int ssl_verify_mode = 0;
struct stat f_stat;
evhtp_ssl_cfg_t* ssl_config = (evhtp_ssl_cfg_t*)calloc(1, sizeof(evhtp_ssl_cfg_t));
ssl_config->ssl_opts = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1;
static struct option long_options[] = {
{ "cert", required_argument, 0, OPTARG_CERT },
{ "key", required_argument, 0, OPTARG_KEY },
{ "ca", required_argument, 0, OPTARG_CA },
{ "capath", required_argument, 0, OPTARG_CAPATH },
{ "ciphers", required_argument, 0, OPTARG_CIPHERS },
{ "verify-peer", no_argument, 0, OPTARG_VERIFY_PEER },
{ "enforce-peer-cert", no_argument, 0, OPTARG_ENFORCE_PEER_CERT },
{ "verify-depth", required_argument, 0, OPTARG_VERIFY_DEPTH },
{ "enable-cache", no_argument, 0, OPTARG_ENABLE_CACHE },
{ "cache-timeout", required_argument, 0, OPTARG_CACHE_TIMEOUT },
{ "cache-size", required_argument, 0, OPTARG_CACHE_SIZE },
{ "enable-protocol", required_argument, 0, OPTARG_ENABLE_PROTOCOL },
{ "disable-protocol", required_argument, 0, OPTARG_DISABLE_PROTOCOL },
{ "ctx-timeout", required_argument, 0, OPTARG_CTX_TIMEOUT },
{ "help", no_argument, 0, 'h' },
{ NULL, 0, 0, 0 }
};
// 获取用户输入的https server参数
while ((opt = getopt_long_only(argc, argv, "", long_options, &long_index)) != -1) {
switch (opt) {
case 'h':
printf(help, argv[0]);
exit(EXIT_FAILURE);
// 服务端证书文件
case OPTARG_CERT:
ssl_config->pemfile = strdup(optarg);
break;
// 服务端秘钥文件
case OPTARG_KEY:
ssl_config->privfile = strdup(optarg);
break;
// 签署服务器证书文件的CA证书文件
case OPTARG_CA:
ssl_config->cafile = strdup(optarg);
break;
case OPTARG_CAPATH:
ssl_config->capath = strdup(optarg);
break;
case OPTARG_CIPHERS:
ssl_config->ciphers = strdup(optarg);
break;
// 签署客户端证书文件的CA证书文件的最大深度
case OPTARG_VERIFY_DEPTH:
ssl_config->verify_depth = atoi(optarg);
break;
// 启用对于客户端的SSL认证
case OPTARG_VERIFY_PEER:
ssl_verify_mode |= SSL_VERIFY_PEER;
break;
// 拒绝没有证书文件的客户端的连接
case OPTARG_ENFORCE_PEER_CERT:
ssl_verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
break;
case OPTARG_ENABLE_CACHE:
ssl_config->scache_type = evhtp_ssl_scache_type_internal;
break;
case OPTARG_CACHE_TIMEOUT:
ssl_config->scache_timeout = atoi(optarg);
break;
case OPTARG_CACHE_SIZE:
ssl_config->scache_size = atoi(optarg);
break;
case OPTARG_CTX_TIMEOUT:
ssl_config->ssl_ctx_timeout = atoi(optarg);
break;
case OPTARG_ENABLE_PROTOCOL:
if (!strcasecmp(optarg, "SSLv2"))
{
ssl_config->ssl_opts &= ~SSL_OP_NO_SSLv2;
}
else if (!strcasecmp(optarg, "SSLv3"))
{
ssl_config->ssl_opts &= ~SSL_OP_NO_SSLv3;
}
else if (!strcasecmp(optarg, "TLSv1"))
{
ssl_config->ssl_opts &= ~SSL_OP_NO_TLSv1;
}
else if (!strcasecmp(optarg, "ALL"))
{
ssl_config->ssl_opts = 0;
}
break;
case OPTARG_DISABLE_PROTOCOL:
if (!strcasecmp(optarg, "SSLv2"))
{
ssl_config->ssl_opts |= SSL_OP_NO_SSLv2;
}
else if (!strcasecmp(optarg, "SSLv3"))
{
ssl_config->ssl_opts |= SSL_OP_NO_SSLv3;
}
else if (!strcasecmp(optarg, "TLSv1"))
{
ssl_config->ssl_opts |= SSL_OP_NO_TLSv1;
}
else if (!strcasecmp(optarg, "ALL"))
{
ssl_config->ssl_opts = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1;
}
break;
default:
break;
} /* switch */
}
// 需要对客户端进行认证的情况
if (ssl_verify_mode != 0)
{
ssl_config->verify_peer = ssl_verify_mode;
ssl_config->x509_verify_cb = ssl__x509_verify_;
}
// 检查服务端证书文件
if (ssl_config->pemfile)
{
if (stat(ssl_config->pemfile, &f_stat) != 0)
{
log_error("Cannot load SSL cert '%s' (%s)", ssl_config->pemfile, strerror(errno));
exit(EXIT_FAILURE);
}
}
// 检查服务端秘钥文件
if (ssl_config->privfile)
{
if (stat(ssl_config->privfile, &f_stat) != 0)
{
log_error("Cannot load SSL key '%s' (%s)", ssl_config->privfile, strerror(errno));
exit(EXIT_FAILURE);
}
}
// 检查签署服务器证书文件的CA证书文件
if (ssl_config->cafile)
{
if (stat(ssl_config->cafile, &f_stat) != 0)
{
log_error("Cannot find SSL CA File '%s' (%s)", ssl_config->cafile, strerror(errno));
exit(EXIT_FAILURE);
}
}
if (ssl_config->capath) {
if (stat(ssl_config->capath, &f_stat) != 0) {
log_error("Cannot find SSL CA PATH '%s' (%s)", ssl_config->capath, strerror(errno));
exit(EXIT_FAILURE);
}
}
return ssl_config;
}
#endif
int main(int argc, char **argv)
{
#ifndef EVHTP_DISABLE_SSL
struct event_base *evbase = event_base_new();
evhtp_alloc_assert(evbase);
evhtp_t *htp = evhtp_new(evbase, NULL);
evhtp_alloc_assert(htp);
// 根据用户输入的https server参数,初始化evhtp的ssl相关配置
evhtp_ssl_init(htp, parse__ssl_opts_(argc, argv));
// 设置回调函数
evhtp_set_gencb(htp, http__callback_, NULL);
// 监听本机IP"192.168.213.133"的4443端口, backlog为128
evhtp_bind_socket(htp, "192.168.213.133", 4443, 128);
log_info("[https server info] https://192.168.213.133:4443/");
/* 进入循环、监听连接,http server开始工作 */
event_base_loop(evbase, 0);
return 0;
#else
log_error(“Not compiled with SSL support, go away”);
return EXIT_FAILURE;
#endif
}
编译生成HTTPS服务器程序,命令如下:
g++ -o https_server https_server.cpp -I/opt/liitdar/libevhtp/libevhtp-1.2.15/include/ -L/opt/liitdar/libevhtp/libevhtp-1.2.15/build/ -levhtp -levent -lpthread -levent_openssl -lssl -lcrypto
**说明:**
* 需要根据实际情况设置头文件路径,并在头文件路径中添加需要的头文件;
* 需要根据实际情况设置静态库 libevhtp.a 的地址;
* 因为libevhtp的静态库 libevhtp.a 中包含了一些ssl的内容,所以在我们使用该静态库时,也需要连接一下ssl的相关库。
### 1.3 测试HTTPS服务器
打开一个终端,运行刚刚生成的HTTPS服务器程序,如下:
./https_server -cert ssl/server-crt.pem -key ssl/server-key.pem
在客户端机器上,打开一个终端,使用curl命令测试HTTPS服务器,如下:
curl https://192.168.213.133:4443/ --cacert ssl/server-crt.pem
![img](https://img-blog.csdnimg.cn/img_convert/9c63a9c1e2cc95628d99e556c444cc3a.png)
![img](https://img-blog.csdnimg.cn/img_convert/fbd12d50651dd3fdd056b8a411645302.png)
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化的资料的朋友,可以添加戳这里获取](https://bbs.csdn.net/topics/618668825)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
-44f9u9Qa-1715797771753)]
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化的资料的朋友,可以添加戳这里获取](https://bbs.csdn.net/topics/618668825)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**