haproxy集成國密ssl功能[下]

上接[haproxy集成國密ssl功能上

4. 源碼修改解析

??以下修改基本圍繞haproxy的ssl_sock.c進行修改來展開的,為了將整個實現邏輯能夠說明清楚,下述內容有部分可能就是直接摘抄haproxy的原有代碼沒有做任何修改,而大部分增加或者修改的內容則進行了特別的說明。

4.1 為bind指令的ssl子命令添加ntls選項解析能力


static struct bind_kw_list bind_kws = { "SSL", { }, {
......{ "force-tlsv10",          bind_parse_tls_method_options, 0 }, /* force TLSv10 */{ "force-tlsv11",          bind_parse_tls_method_options, 0 }, /* force TLSv11 */{ "force-tlsv12",          bind_parse_tls_method_options, 0 }, /* force TLSv12 */{ "force-tlsv13",          bind_parse_tls_method_options, 0 }, /* force TLSv13 */{ "force-ntlsv11",         bind_parse_tls_method_options, 0 }, /* force NTLSv11 */{ "generate-certificates", bind_parse_generate_certs,     0 }, /* enable the server certificates generation */{ "no-ca-names",           bind_parse_no_ca_names,        0 }, /* do not send ca names to clients (ca_file related) */{ "no-sslv3",              bind_parse_tls_method_options, 0 }, /* disable SSLv3 */{ "no-tlsv10",             bind_parse_tls_method_options, 0 }, /* disable TLSv10 */{ "no-tlsv11",             bind_parse_tls_method_options, 0 }, /* disable TLSv11 */{ "no-tlsv12",             bind_parse_tls_method_options, 0 }, /* disable TLSv12 */{ "no-ntlsv11",            bind_parse_tls_method_options, 0 }, /* disable TLSv13 */{ "no-tlsv13",             bind_parse_tls_method_options, 0 }, /* disable NTLSv11 */
......{ NULL, NULL, 0 },
}};

??這里添加了ntls、force-ntlsv11和no-ntlsv11三個指令選項。haproxy 通過INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);將指令選項的解析回調函數注冊進去,在指令解析的時候將回調對應的選項解析函數。

4.1.1 ntls指令選項解析

??按照上面的配置,ntls的配置選項是交由bind_parse_ntls來解析的,源碼如下:


/* parse the "ntls" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
static int bind_parse_ntls(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
{char enc[MAXPATHLEN], sign[MAXPATHLEN], tls[MAXPATHLEN];int cfgerr = 0;int couple_cert = 0;const char *gm_cert_enc, *gm_cert_sign, *tls_cert;gm_cert_enc = gm_cert_sign = tls_cert = NULL;char* err2 = NULL;SSL_CTX *old_ctx = NULL;if (!*args[cur_arg + 1]) {memprintf(err, "'%s' : missing ntls enc certificate location", args[cur_arg]);return ERR_ALERT | ERR_FATAL;}else {gm_cert_enc = args[cur_arg + 1];}if (!*args[cur_arg + 2]) {memprintf(err, "'%s' : missing ntls sign certificate location", args[cur_arg]);return ERR_ALERT | ERR_FATAL;}else {gm_cert_sign = args[cur_arg + 2];}if (*args[cur_arg + 3]) {if (strstr(args[cur_arg + 3], ".pem") != NULL || strstr(args[cur_arg + 3], ".crt") != NULL) {/* 第三個參數必須是以.pem或.crt為擴展名的文件,這樣子才會啟用tls 和 ntls雙證書模式 */couple_cert  = 1;tls_cert     = args[cur_arg + 1];gm_cert_enc  = args[cur_arg + 2];gm_cert_sign = args[cur_arg + 3];}}if (tls_cert) {if ((*tls_cert != '/' ) && global_ssl.crt_base) {if ((strlen(global_ssl.crt_base) + 1 + strlen(tls_cert) + 1) > MAXPATHLEN) {memprintf(err, "'%s' : tls certificate path too long", args[cur_arg]);return ERR_ALERT | ERR_FATAL;}snprintf(tls, sizeof(tls), "%s/%s",  global_ssl.crt_base, tls_cert);}else {strcpy(tls, tls_cert);}/* 加載tls證書 */cfgerr = ssl_sock_load_cert(tls, conf, &err2);if (cfgerr != 0) {memprintf(err, "load enc certificate %s failed, error:%s", tls, err2 ? err2: "" );if (err2) free(err2);return cfgerr;}}else {/* 如果沒有tls證書,那么就沒有調用ssl_sock_load_cert而創建一個新的ctx,在這里需要將conf->default_ctx置為空,讓ssl_sock_load_ntls_cert新創建一個ctx,等ntls的enc和sign證書加載完成后,重新將conf->default_ctx設置回去。*/old_ctx = conf->default_ctx;conf->default_ctx = NULL;}if ((*gm_cert_enc != '/' ) && global_ssl.crt_base) {if ((strlen(global_ssl.crt_base) + 1 + strlen(gm_cert_enc) + 1) > MAXPATHLEN) {memprintf(err, "'%s' : enc certificate path too long", args[cur_arg]);return ERR_ALERT | ERR_FATAL;}snprintf(enc, sizeof(enc), "%s/%s",  global_ssl.crt_base, gm_cert_enc);}else {strcpy(enc, gm_cert_enc);}/* 加載ntls_enc證書 */cfgerr = ssl_sock_load_ntls_cert(enc, conf, 0, &err2);if (cfgerr != 0) {memprintf(err, "load enc certificate %s failed, error:%s",enc, err2 ? err2 : "");if (err2) free(err2);return cfgerr;}if ((*gm_cert_sign != '/' ) && global_ssl.crt_base) {if ((strlen(global_ssl.crt_base) + 1 + strlen(gm_cert_sign) + 1) > MAXPATHLEN) {memprintf(err, "'%s' : sign certificate path too long", args[cur_arg]);return ERR_ALERT | ERR_FATAL;}snprintf(sign, sizeof(sign), "%s/%s",  global_ssl.crt_base, gm_cert_sign);}else {strcpy(sign, gm_cert_sign);}/* 加載ntls_sign證書 */cfgerr = ssl_sock_load_ntls_cert(sign, conf, 1, &err2);if (cfgerr != 0) {memprintf(err, "load sign certificate %s failed, error:%s", sign, err2 ? err2 : "" );if (err2) free(err2);return cfgerr;}// 設置啟用國密TLCP協議conf->enable_ntls = 1;/* 重新將default_ctx改成之前的old_ctx */if (old_ctx) {conf->default_ctx = old_ctx;}if (tls_cert) return cfgerr | 0x30000000;         /* 指明消耗3個參數 */elsereturn cfgerr | 0x20000000;         /* 指明消耗2個參數 */
}

??以上代碼就是從配置指令中讀取加密證書和簽名證書,ntls可以同時支持國際和國密證書的加載,如果是雙證書的情況,那么需要解析三個參數,所以返回的時候我們需要告訴配置解析框架到底消耗了幾個參數,這個通過復用返回的錯誤值的高4個bit來實現。由于原來的haproxy框架是不支持可變個數參數的,因此,在兼容原始功能邏輯的基礎上,需要略微修改一下haproxy的配置解析框架的代碼,在cfg_parse-listen.c的cfg_parse_listen函數中,進行如下修改:

int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
{
......cur_arg = 2;while (*(args[cur_arg])) {static int bind_dumped;struct bind_kw *kw;char *err;kw = bind_find_kw(args[cur_arg]);if (kw) {char *err = NULL;int code, skip = 0;if (!kw->parse) {ha_alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",file, linenum, args[0], args[1], args[cur_arg]);cur_arg += 1 + kw->skip ;err_code |= ERR_ALERT | ERR_FATAL;goto out;}code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);/* skip表示回調函數在配置選項解析過程中,消耗了幾個配置參數 */skip = (code >> 28) & 0x0000000F;  /* 從返回值中過濾出錯誤代碼 */ err_code |= code & 0x0FFFFFFF;/* 用來兼容原生邏輯,如果解析函數沒有返回了跳過多少個參數,則用配置中的設置 */if (skip == 0) {skip = kw->skip;}if (code & 0x0FFFFFFF) {  /* 如果本次調用配置解析回調函數返回錯誤了, 那么下面進行錯誤處理 */if (err && *err) {indent_msg(&err, 2);if (((code & (ERR_WARN|ERR_ALERT)) == ERR_WARN))ha_warning("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);elseha_alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);}elseha_alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",file, linenum, args[0], args[1], args[cur_arg]);if (code & ERR_FATAL) {free(err);cur_arg += 1 + skip;goto out;}}free(err);cur_arg += 1 + skip;continue;}err = NULL;if (!bind_dumped) {bind_dump_kws(&err);indent_msg(&err, 4);bind_dumped = 1;}ha_alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",file, linenum, args[0], args[1], args[cur_arg],err ? " Registered keywords :" : "", err ? err : "");free(err);err_code |= ERR_ALERT | ERR_FATAL;goto out;}goto out;
......
}

??函數bind_parse_ntls是通過ssl_sock_load_ntls_cert來將這兩個證書加載進bind_conf->default_ctx(ssl配置上下文),ssl_sock_load_ntls_cert代碼如下:

#define FREE_CTX_RETURN(ctx, err)    		\if (ctx_new) {   					\SSL_CTX_free(ctx);  			\bind_conf->default_ctx = NULL; 	\}									\return (err)/* enc_sign = 0 表示加載加密證書  否則表示加載簽名證書 */
static
int ssl_sock_load_ntls_cert(char 

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/717512.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/717512.shtml
英文地址,請注明出處:http://en.pswp.cn/news/717512.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

基于springboot+vue的疾病防控綜合系統

博主主頁&#xff1a;貓頭鷹源碼 博主簡介&#xff1a;Java領域優質創作者、CSDN博客專家、阿里云專家博主、公司架構師、全網粉絲5萬、專注Java技術領域和畢業設計項目實戰&#xff0c;歡迎高校老師\講師\同行交流合作 ?主要內容&#xff1a;畢業設計(Javaweb項目|小程序|Pyt…

計算機設計大賽 深度學習貓狗分類 - python opencv cnn

文章目錄 0 前言1 課題背景2 使用CNN進行貓狗分類3 數據集處理4 神經網絡的編寫5 Tensorflow計算圖的構建6 模型的訓練和測試7 預測效果8 最后 0 前言 &#x1f525; 優質競賽項目系列&#xff0c;今天要分享的是 &#x1f6a9; **基于深度學習貓狗分類 ** 該項目較為新穎&a…

Python測試框架pytest介紹用法

1、介紹 pytest是python的一種單元測試框架&#xff0c;同自帶的unittest測試框架類似&#xff0c;相比于unittest框架使用起來更簡潔、效率更高 pip install -U pytest 特點&#xff1a; 1.非常容易上手,入門簡單,文檔豐富&#xff0c;文檔中有很多實例可以參考 2.支持簡單的單…

C++內存模型與內存序

寫在前面 在真正了解Memory Order的作用之前&#xff0c;曾經簡單地將Memory Order等同于mutex和atomic來進行線程間數據同步&#xff0c;或者用來限制線程間的執行順序&#xff0c;其實這是一個錯誤的理解。直到后來仔細研究了Memory Order之后&#xff0c;才發現無論是功能還…

Android 12 設置默認的屏幕亮度百分比

1、安卓每個版本的更新&#xff0c; 其核心代碼也會隨之更新&#xff0c;本次為Android 12 版本默認屏幕亮度的修改。 其中涉及的核心代碼主要有&#xff1a; packages\apps\Settings\src\com\android\settings\display\BrightnessLevelPreferenceController.java frameworks…

力扣706:設計哈希映射

題目&#xff1a; 不使用任何內建的哈希表庫設計一個哈希映射&#xff08;HashMap&#xff09;。 實現 MyHashMap 類&#xff1a; MyHashMap() 用空映射初始化對象void put(int key, int value) 向 HashMap 插入一個鍵值對 (key, value) 。如果 key 已經存在于映射中&#x…

【GPU驅動開發】- mesa編譯與鏈接過程詳細分析

前言 不必害怕未知&#xff0c;無需恐懼犯錯&#xff0c;做一個Creator&#xff01; 一、總體框架圖 暫時無法在飛書文檔外展示此內容 二、Mesa API 處理 OpenGL 函數調用 Mesa API 負責實現 OpenGL 和其他圖形 API 的函數接口。Mesa API 表是一個重要的數據結構&#xf…

c# 獲得進程的標題

使用 System.Diagnostics.Process 類來獲取所有 Internet Explorer 進程的標題。以下是如何做到這一點的代碼示例&#xff1a; using System; using System.Diagnostics;class Program {static void Main(){foreach (Process process in Process.GetProcessesByName("iex…

數據中臺的演進與實踐——構建企業的數字核心_光點科技

數據中臺&#xff0c;一個在近年來被頻繁提及的概念&#xff0c;已經成為眾多企業數字化轉型的核心組成部分。然而&#xff0c;盡管它的重要性被業界廣泛認可&#xff0c;對于數據中臺的深入理解和有效實踐仍然是許多企業面臨的挑戰。在本文中&#xff0c;我們將從數據中臺的演…

從租完ecs云服務器 使用docker建立用戶 全過程

一 登錄root用戶 ssh root公網ip 輸入密碼&#xff0c;若沒有密碼可以前往阿里云設置服務器root密碼 二 創建新用戶 并賦予 新用戶sudo權限 adduser $USER usermod -aG sudo $USER 三 Ubuntu安裝docker sudo apt-get remove docker docker-engine docker.io containerd ru…

藍橋杯:門牌制作

題目 小藍要為一條街的住戶制作門牌號。 這條街一共有2020 位住戶&#xff0c;門牌號從1 到2020 編號。 小藍制作門牌的方法是先制作0 到9 這幾個數字字符&#xff0c;最后根據需要將字符粘貼到門牌上&#xff0c;例如門牌1017 需要依次粘貼字符1、0、1、7&#xff0c;即需要1…

反向代理原理

反向代理是一種網絡應用架構模式&#xff0c;主要用于將對一個或多個后端服務器的請求進行轉發、負載均衡和緩存&#xff0c;以提高系統的安全性、性能和可靠性。 其原理如下&#xff1a; 1. 客戶端向反向代理發送請求。 2. 反向代理服務器接收請求&#xff0c;并根據預設的規…

基于window安裝Elasticsearch詳細教程

目錄 一、安裝Java環境1.1 Java版本選擇 二、下載和安裝ES2.1 下載地址2.2 文件目錄 3、啟動服務3.1 以管理員身份打開cmd3.2 首次登錄會有密碼&#xff0c;需要記住3.3 訪問 一、安裝Java環境 1.1 Java版本選擇 官網地址&#xff1a;https://www.elastic.co/cn/support/matr…

9個接口性能優化方案,RT從9000ms到180ms

昨天接到生產 SkyWalking 鏈路監控告警: 服務的百分位數響應時間在過去的 10 分鐘內超過 2000 毫秒的次數達到 3 次。 經過不斷的優化&#xff0c;將接口從 9000ms 優化到 180ms&#xff0c;先看結果 優化前&#xff1a; 優化后&#xff1a; 廢話不多我們開始 一、定位性能差的…

Maven實戰(2)之搭建maven私服

一, 背景: 如果使用國外鏡像,下載速度比較慢; 如果使用阿里云鏡像,速度還算OK,但是假如網速不好的時候,其實也是比較慢的; 如果沒有網的情況下更加下載不了. 二, 本地倉庫、個人/公司私服、遠程倉庫關系如下: 三, 下載安裝nexus私服 略

Notepad3:告別Windows記事本,輕松進行文本編輯

名人說&#xff1a;莫道桑榆晚&#xff0c;為霞尚滿天。——劉禹錫&#xff08;劉夢得&#xff0c;詩豪&#xff09; 創作者&#xff1a;Code_流蘇(CSDN)&#xff08;一個喜歡古詩詞和編程的Coder&#x1f60a;&#xff09; 目錄 一、什么是Notepad3&#xff1f;①Notepad3②核…

openGauss學習筆記-234 openGauss性能調優-系統調優-資源負載管理-資源管理準備-設置控制組

文章目錄 openGauss學習筆記-234 openGauss性能調優-系統調優-資源負載管理-資源管理準備-設置控制組234.1 背景信息234.2 前提條件234.3 操作步驟234.3.1 創建子Class控制組和Workload控制組234.3.2 更新控制組的資源配額234.3.3 刪除控制組 234.4 查看控制組的信息 openGauss…

第八節 龍晰Anolis 8.8 安裝 DDE 桌面環境

一、前言 最小化安裝的龍晰 Anolis OS 8.8 是不帶圖形化界面的&#xff0c;只能使用命令行&#xff0c;有些時候需要用到桌面環境&#xff0c;而DDE (Deepin Desktop Enviroment) 就是很好的桌面環境&#xff0c;它是指龍晰 Anolis 所搭載的中國自主桌面環境&#xff0c;用起來…

客戶快遞信息管理系統——導入文件識別存儲

客戶快遞信息管理系統背景&#xff1a; 目前不少公司都提供網購服務&#xff0c;為了將商品快遞給客戶&#xff0c;就必須保存和管理客戶的姓名、電話號碼、郵寄地址等信息。為此&#xff0c;本項目要求完成一個小型客戶快遞信息管理系統&#xff0c;完成對客戶快遞信息的建立…

C++構造函數析構函數

構造和析構函數用于管理對象的初始化和清理工作&#xff0c;確保對象的正確生命周期管理。以下是其重要特性&#xff1a; 構造函數不能是虛函數 從存儲空間角度&#xff1a; 虛函數是需要通過虛函數表和虛指針來調用的&#xff0c;如果用虛函數實現構造函數&#xff0c;而對象…