From 28810b62c8c4630c07a0912ebc56844ea84bd50f Mon Sep 17 00:00:00 2001 From: zhanghongtong Date: Thu, 15 Apr 2021 09:35:07 +0800 Subject: [PATCH] fix(ws connection): fix peer_cert_as_username error when ws connect --- etc/emqx.conf | 22 ++++++++++++++++++++++ priv/emqx.schema | 8 ++++++++ src/emqx.appup.src | 32 +++++++++++++++++++++++++------- src/emqx_ws_connection.erl | 22 ++++++++++++++-------- 4 files changed, 69 insertions(+), 15 deletions(-) diff --git a/etc/emqx.conf b/etc/emqx.conf index d6d8eb3b1..033612e00 100644 --- a/etc/emqx.conf +++ b/etc/emqx.conf @@ -1088,10 +1088,18 @@ listener.tcp.external.access.1 = allow all ## Enable the option for X.509 certificate based authentication. ## EMQX will use the common name of certificate as MQTT username. +## Only support Proxy Protocol V2, the CN is available in Proxy Protocol V2 additional info ## ## Value: cn | dn | crt ## listener.tcp.external.peer_cert_as_username = cn +## Enable the option for X.509 certificate based authentication. +## EMQX will use the common name of certificate as MQTT clientid. +## Only support Proxy Protocol V2, the CN is available in Proxy Protocol V2 additional info +## +## Value: cn +## listener.tcp.external.peer_cert_as_clientid = cn + ## The TCP backlog defines the maximum length that the queue of pending ## connections can grow to. ## @@ -1567,6 +1575,20 @@ listener.ws.external.verify_protocol_header = on ## Value: Duration ## listener.ws.external.proxy_protocol_timeout = 3s +## Enable the option for X.509 certificate based authentication. +## EMQX will use the common name of certificate as MQTT username. +## Only support Proxy Protocol V2, the CN is available in Proxy Protocol V2 additional info +## +## Value: cn +## listener.ws.external.peer_cert_as_username = cn + +## Enable the option for X.509 certificate based authentication. +## EMQX will use the common name of certificate as MQTT clientid. +## Only support Proxy Protocol V2, the CN is available in Proxy Protocol V2 additional info +## +## Value: cn +## listener.ws.external.peer_cert_as_clientid = cn + ## The TCP backlog of external MQTT/WebSocket Listener. ## ## See: listener.ws.$name.backlog diff --git a/priv/emqx.schema b/priv/emqx.schema index 54c107016..88ef03546 100644 --- a/priv/emqx.schema +++ b/priv/emqx.schema @@ -1572,6 +1572,14 @@ end}. hidden ]}. +{mapping, "listener.ws.$name.peer_cert_as_username", "emqx.listeners", [ + {datatype, {enum, [cn]}} +]}. + +{mapping, "listener.ws.$name.peer_cert_as_clientid", "emqx.listeners", [ + {datatype, {enum, [cn]}} +]}. + %%-------------------------------------------------------------------- %% MQTT/WebSocket/SSL Listeners diff --git a/src/emqx.appup.src b/src/emqx.appup.src index cc436053c..805b55bb2 100644 --- a/src/emqx.appup.src +++ b/src/emqx.appup.src @@ -8,23 +8,29 @@ end, {VSN, [ + {"4.2.10", [ + {load_module, emqx_ws_connection, brutal_purge, soft_purge, []} + ]}, {"4.2.9", [ {load_module, emqx_connection, brutal_purge, soft_purge, []}, {load_module, emqx_ws_connection, brutal_purge, soft_purge, []} ]}, {<<"4.2.[34567]">>, [ - {load_module, emqx_frame, brutal_purge, soft_purge, []} + {load_module, emqx_frame, brutal_purge, soft_purge, []}, + {load_module, emqx_ws_connection, brutal_purge, soft_purge, []} ]}, {"4.2.2", [ {load_module, emqx_frame, brutal_purge, soft_purge, []}, - {load_module, emqx_metrics, brutal_purge, soft_purge, []} + {load_module, emqx_metrics, brutal_purge, soft_purge, []}, + {load_module, emqx_ws_connection, brutal_purge, soft_purge, []} ]}, {"4.2.1", [ {load_module, emqx_frame, brutal_purge, soft_purge, []}, {load_module, emqx_metrics, brutal_purge, soft_purge, []}, {load_module, emqx_channel, brutal_purge, soft_purge, []}, {load_module, emqx_mod_topic_metrics, brutal_purge, soft_purge, []}, - {load_module, emqx_json, brutal_purge, soft_purge, []} + {load_module, emqx_json, brutal_purge, soft_purge, []}, + {load_module, emqx_ws_connection, brutal_purge, soft_purge, []} ]}, {"4.2.0", [ {load_module, emqx_frame, brutal_purge, soft_purge, []}, @@ -32,6 +38,7 @@ {load_module, emqx_channel, brutal_purge, soft_purge, []}, {load_module, emqx_mod_topic_metrics, brutal_purge, soft_purge, []}, {load_module, emqx_json, brutal_purge, soft_purge, []}, + {load_module, emqx_ws_connection, brutal_purge, soft_purge, []} {apply, {application, set_env, [emqx, force_shutdown_policy, #{message_queue_len => DefaultLen, @@ -40,26 +47,37 @@ {<<".*">>, []} ], [ + {"4.2.10", [ + {load_module, emqx_ws_connection, brutal_purge, soft_purge, []} + ]}, + {"4.2.9", [ + {load_module, emqx_connection, brutal_purge, soft_purge, []}, + {load_module, emqx_ws_connection, brutal_purge, soft_purge, []} + ]}, {<<"4.2.[34567]">>, [ - {load_module, emqx_frame, brutal_purge, soft_purge, []} + {load_module, emqx_frame, brutal_purge, soft_purge, []}, + {load_module, emqx_ws_connection, brutal_purge, soft_purge, []} ]}, {"4.2.2", [ {load_module, emqx_frame, brutal_purge, soft_purge, []}, - {load_module, emqx_metrics, brutal_purge, soft_purge, []} + {load_module, emqx_metrics, brutal_purge, soft_purge, []}, + {load_module, emqx_ws_connection, brutal_purge, soft_purge, []} ]}, {"4.2.1", [ {load_module, emqx_frame, brutal_purge, soft_purge, []}, {load_module, emqx_metrics, brutal_purge, soft_purge, []}, {load_module, emqx_channel, brutal_purge, soft_purge, []}, {load_module, emqx_mod_topic_metrics, brutal_purge, soft_purge, []}, - {load_module, emqx_json, brutal_purge, soft_purge, []} + {load_module, emqx_json, brutal_purge, soft_purge, []}, + {load_module, emqx_ws_connection, brutal_purge, soft_purge, []} ]}, {"4.2.0", [ {load_module, emqx_frame, brutal_purge, soft_purge, []}, {load_module, emqx_metrics, brutal_purge, soft_purge, []}, {load_module, emqx_channel, brutal_purge, soft_purge, []}, {load_module, emqx_mod_topic_metrics, brutal_purge, soft_purge, []}, - {load_module, emqx_json, brutal_purge, soft_purge, []} + {load_module, emqx_json, brutal_purge, soft_purge, []}, + {load_module, emqx_ws_connection, brutal_purge, soft_purge, []} ]}, {<<".*">>, []} ] diff --git a/src/emqx_ws_connection.erl b/src/emqx_ws_connection.erl index 561e1d2fe..07578f2ad 100644 --- a/src/emqx_ws_connection.erl +++ b/src/emqx_ws_connection.erl @@ -196,15 +196,21 @@ init(Req, Opts) -> end. websocket_init([Req, Opts]) -> - Peername = case proplists:get_bool(proxy_protocol, Opts) - andalso maps:get(proxy_header, Req) of - #{src_address := SrcAddr, src_port := SrcPort} -> - {SrcAddr, SrcPort}; - _ -> - cowboy_req:peer(Req) - end, + {Peername, Peercert} = + case proplists:get_bool(proxy_protocol, Opts) + andalso maps:get(proxy_header, Req) of + #{src_address := SrcAddr, src_port := SrcPort, ssl := SSL} -> + ProxyName = {SrcAddr, SrcPort}, + %% Notice: Only CN is available in Proxy Protocol V2 additional info + ProxySSL = case maps:get(cn, SSL, undefined) of + undeined -> nossl; + CN -> [{pp2_ssl_cn, CN}] + end, + {ProxyName, ProxySSL}; + _ -> + {cowboy_req:peer(Req), cowboy_req:cert(Req)} + end, Sockname = cowboy_req:sock(Req), - Peercert = cowboy_req:cert(Req), WsCookie = try cowboy_req:parse_cookies(Req) catch error:badarg ->