// OpenSSL DTLS 握手状态转移图
//
// 请使用 Visual Studio Code 编辑此文件
// 安装 "Graphviz Interactive Preview" 插件后, 使用快捷键 Ctrl+Shift+Vdigraph top {//rankdir = LR; // LR表示沿着水平方向绘图, 默认情况会沿垂直方向绘图size = "20";compound = true;margin = "20,20";ranksep = 0.2;penwidth = 0.5;// 服务器状态机subgraph cluster_server {margin="10,10"labeljust="left"label = "服务器状态机"style=filledfillcolor=gray95node [shape = doublecircle]; DTLS服务器初始状态 TLS_ST_OK_ 准备重新握手_;node [shape = circle];DTLS服务器初始状态 -> 20 [ label = "收到Client Hello" ];20 -> 21 [ label = "输出Hello Verify包" ];21 -> 20 [ label = "收到带cookie的ClientHello包" ];20 -> 22 [ label = "cookie校验无误\n输出Server Hello包" ];22 -> 23 [ label = "输出Certificate\n服务器证书包" ];23 -> 34 [ label = "输出Server Certificate Status包" ];23 -> 24 [ label = "输出Server Key Exchange包" ];34 -> 24 [ label = "输出Server Key Exchange包" ];24 -> 26 [ label = "输出Server Hello Done\n(允许单向身份认证)" ];24 -> 25 [ label = "输出Certificate Request\n(强制双向身份认证)" ];25 -> 26 [ label = "输出Server Hello Done包" ];26 -> 27 [ label = "收到客户端的Certificate证书包" ];27 -> 28 [ label = "收到Client Key Exchange" ];28 -> 31 [ label = "收到Change Cipher Spec" ];28 -> 29 [ label = "收到Certificate Verify包\n(双向证书认证)" ];29 -> 31 [ label = "收到Change Cipher Spec" ];31 -> 32 [ label = "收到Client Finished" ];32 -> 35 [ label = "输出Change Cipher Spec包" ];32 -> 33 [ label = "输出New Session Ticket包" ];33 -> 35 [ label = "输出Change Cipher Spec包" ];35 -> 36 [ label = "输出Server Finished包" ];36 -> TLS_ST_OK_ [ label = "握手完成" ];TLS_ST_OK_ -> 准备重新握手_ [ label = "输出Hello Request\n(重握手请求)" ];准备重新握手_ -> TLS_ST_OK_ [ label = "允许客户端不响应重握手请求" ];准备重新握手_ -> 20 [ label = "<=强制重握手\n等待Client Hello" ];}// 客户端状态机subgraph cluster_client {margin="20,20";labeljust="left";label = "客户端状态机";style=filled;fillcolor=gray95node [shape = doublecircle]; DTLS客户端初始状态 TLS_ST_OK 准备重新握手;node [shape = circle];DTLS客户端初始状态 -> 12 [ label = "输出Client Hello包" ];12 -> 2 [ label = "收到Hello Verify\n(含有对方下发的cookie)" ];2 -> 12 [ label = "输出带cookie的ClientHello包" ];12 -> 3 [ label = "收到Server Hello" ];3 -> 4 [ label = "收到Certificate\n(服务器证书)" ];4 -> 6 [ label = "收到Server Key Exchange" ];4 -> 5 [ label = "收到Server Certificate Status" ];5 -> 6 [ label = "收到Server Key Exchange" ];6 -> 8 [ label = "收到Server Hello Done\n(不强制双向身份认证)" ];6 -> 7 [ label = "收到Certificate Request\n(强制双向身份认证)" ];7 -> 8 [ label = "收到Server Hello Done" ];8 -> 13 [ label = "客户端输出Certificate证书包" ];13 -> 14 [ label = "输出Client Key Exchange包" ];14 -> 16 [ label = "输出Change Cipher Spec包\n(允许单向证书认证)" ];14 -> 15 [ label = "输出Certificate Verify包\n(双向证书认证)" ];15 -> 16 [ label = "输出Change Cipher Spec包" ];16 -> 18 [ label = "输出Client Finished包" ];18 -> 10 [ label = "收到Change Cipher Spec" ];18 -> 9 [ label = "收到New Session Ticket" ];9 -> 10 [ label = "收到Change Cipher Spec" ];10 -> 11 [ label = "收到Server Finished" ];11 -> TLS_ST_OK [ label = "握手完成" ];TLS_ST_OK -> 准备重新握手 [ label = "收到Hello Request" ];准备重新握手 -> TLS_ST_OK [ label = "忽略重握手请求" ];准备重新握手 -> 12 [ label = "<=执行重握手,输出Client Hello包" ];}}

DTLS握手状态机-编程之家 image.png

    // 客户端初始状态DTLS服务器初始状态 -> TLS_ST_CW_CLNT_HELLO [ label = "创建Client Hello包并发送" ];// TLS_ST_CW_CLNT_HELLO -> HELLO_VERIFY_REQUEST [ label = "收到Hello Verify包" ];// HELLO_VERIFY_REQUEST -> TLS_ST_CW_CLNT_HELLO [ label = "从Hello Verify包中取出cookie" ];// TLS_ST_CW_CLNT_HELLO -> TLS_ST_CR_SRVR_HELLO [ label = "..." ];// TLS_ST_CR_SRVR_HELLO -> TLS_ST_CR_CERT [ label = "..." ];// TLS_ST_CR_CERT -> TLS_ST_CR_CERT_STATUS [ label = "..." ];// TLS_ST_CR_CERT_STATUS -> TLS_ST_CR_KEY_EXCH [ label = "..." ];// TLS_ST_CR_CERT -> TLS_ST_CR_KEY_EXCH [ label = "..." ];// TLS_ST_CR_KEY_EXCH -> TLS_ST_CR_CERT_REQ [ label = "..." ];// TLS_ST_CR_CERT_REQ -> TLS_ST_CR_SRVR_DONE [ label = "..." ];// TLS_ST_CR_SRVR_DONE -> TLS_ST_CW_CERT [ label = "服务器强制双向TLS" ];