使用libevhtp搭建HTTPS SERVER(单向验证身份)_evhtp使用方法(2)

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事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 : Directory of PEM-encoded CA Certificates for Client Auth\n"
" -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行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值