diff --git a/apps/emqx/test/emqx_common_test_helpers.erl b/apps/emqx/test/emqx_common_test_helpers.erl index 6f2b05161..96fd83438 100644 --- a/apps/emqx/test/emqx_common_test_helpers.erl +++ b/apps/emqx/test/emqx_common_test_helpers.erl @@ -65,6 +65,11 @@ select_free_port/1 ]). +-export([ + ssl_verify_fun_allow_any_host/0, + ssl_verify_fun_allow_any_host_impl/3 +]). + -export([ emqx_cluster/1, emqx_cluster/2, @@ -1421,3 +1426,24 @@ group_path(Config) -> _:_ -> [] end. + +%% almost verify_none equivalent, but only ignores 'hostname_check_failed' +ssl_verify_fun_allow_any_host_impl(_Cert, Event, State) -> + case Event of + valid -> + {valid, State}; + valid_peer -> + {valid, State}; + {bad_cert, hostname_check_failed} -> + {valid, State}; + {bad_cert, _} -> + {fail, Event}; + {extension, _} -> + {unknown, State} + end. + +ssl_verify_fun_allow_any_host() -> + [ + {verify, verify_peer}, + {verify_fun, {fun ?MODULE:ssl_verify_fun_allow_any_host_impl/3, _State = #{}}} + ]. diff --git a/apps/emqx_gateway/src/emqx_gateway_schema.erl b/apps/emqx_gateway/src/emqx_gateway_schema.erl index c0abb48ce..ed54383f5 100644 --- a/apps/emqx_gateway/src/emqx_gateway_schema.erl +++ b/apps/emqx_gateway/src/emqx_gateway_schema.erl @@ -174,7 +174,11 @@ fields(dtls_opts) -> reuse_sessions => true, versions => dtls_all_available }, - false + %% NOTE + %% Although dTLS listener is started through `esockd`, it doesn't really support stuff + %% more tightly related to `emqx_listeners` (`enable_crl_check`, `oscp`) and plain TLS + %% (`gc_after_handshake`). + _IsRanchListener = true ). desc(gateway) -> diff --git a/apps/emqx_gateway_mqttsn/test/emqx_sn_protocol_SUITE.erl b/apps/emqx_gateway_mqttsn/test/emqx_sn_protocol_SUITE.erl index 0c4c4e6bf..4f69fc271 100644 --- a/apps/emqx_gateway_mqttsn/test/emqx_sn_protocol_SUITE.erl +++ b/apps/emqx_gateway_mqttsn/test/emqx_sn_protocol_SUITE.erl @@ -66,7 +66,6 @@ -elvis([{elvis_style, dont_repeat_yourself, disable}]). -define(CONF_DEFAULT, << - "\n" "gateway.mqttsn {\n" " gateway_id = 1\n" " broadcast = true\n" @@ -86,6 +85,14 @@ " listeners.udp.default {\n" " bind = 1884\n" " }\n" + " listeners.dtls.default {\n" + " bind = 1885\n" + " dtls_options {\n" + " cacertfile = \"${certdir}ca.crt\"\n" + " certfile = \"${certdir}dtls.server.crt\"\n" + " keyfile = \"${certdir}dtls.server.key\"\n" + " }\n" + " }\n" "}\n" >>). @@ -97,9 +104,13 @@ all() -> emqx_common_test_helpers:all(?MODULE). init_per_suite(Config) -> + ConfTemplate = emqx_template:parse(?CONF_DEFAULT), + Conf = emqx_template:render_strict(ConfTemplate, #{ + certdir => ?config(data_dir, Config) + }), Apps = emqx_cth_suite:start( [ - {emqx_conf, ?CONF_DEFAULT}, + {emqx_conf, Conf}, emqx_gateway, emqx_auth, emqx_management, @@ -191,6 +202,25 @@ t_first_disconnect(_) -> ?assertEqual(<<2, ?SN_DISCONNECT>>, receive_response(Socket)), gen_udp:close(Socket). +t_connect_dtls(Config) -> + SockName = {'mqttsn:dtls:default', 1885}, + ?assertEqual(true, lists:keymember(SockName, 1, esockd:listeners())), + + ClientOpts = [ + binary, + {active, false}, + {protocol, dtls}, + {cacertfile, filename:join(?config(data_dir, Config), "ca.crt")} + | emqx_common_test_helpers:ssl_verify_fun_allow_any_host() + ], + {ok, Socket} = ssl:connect(?HOST, 1885, ClientOpts, 1000), + ok = ssl:send(Socket, make_connect_msg(<<"client_id_test1">>, 1)), + ?assertEqual({ok, <<3, ?SN_CONNACK, 0>>}, ssl:recv(Socket, 0, 1000)), + + ok = ssl:send(Socket, make_disconnect_msg(undefined)), + ?assertEqual({ok, <<2, ?SN_DISCONNECT>>}, ssl:recv(Socket, 0, 1000)), + ssl:close(Socket). + t_subscribe(_) -> Dup = 0, QoS = 0, @@ -2444,10 +2474,7 @@ send_searchgw_msg(Socket) -> Radius = 0, ok = gen_udp:send(Socket, ?HOST, ?PORT, <>). -send_connect_msg(Socket, ClientId) -> - send_connect_msg(Socket, ClientId, 1). - -send_connect_msg(Socket, ClientId, CleanSession) when +make_connect_msg(ClientId, CleanSession) when CleanSession == 0; CleanSession == 1 -> @@ -2460,9 +2487,14 @@ send_connect_msg(Socket, ClientId, CleanSession) when TopicIdType = 0, ProtocolId = 1, Duration = 10, - Packet = - <>, + <>. + +send_connect_msg(Socket, ClientId) -> + send_connect_msg(Socket, ClientId, 1). + +send_connect_msg(Socket, ClientId, CleanSession) -> + Packet = make_connect_msg(ClientId, CleanSession), ok = gen_udp:send(Socket, ?HOST, ?PORT, Packet). send_connect_msg_with_will(Socket, Duration, ClientId) -> @@ -2724,15 +2756,17 @@ send_pingreq_msg(Socket, ClientId) -> ?LOG("send_pingreq_msg ClientId=~p", [ClientId]), ok = gen_udp:send(Socket, ?HOST, ?PORT, PingReqPacket). -send_disconnect_msg(Socket, Duration) -> +make_disconnect_msg(Duration) -> Length = 2, Length2 = 4, MsgType = ?SN_DISCONNECT, - DisConnectPacket = - case Duration of - undefined -> <>; - Other -> <> - end, + case Duration of + undefined -> <>; + Other -> <> + end. + +send_disconnect_msg(Socket, Duration) -> + DisConnectPacket = make_disconnect_msg(Duration), ?LOG("send_disconnect_msg Duration=~p", [Duration]), ok = gen_udp:send(Socket, ?HOST, ?PORT, DisConnectPacket). diff --git a/apps/emqx_gateway_mqttsn/test/emqx_sn_protocol_SUITE_data/ca.crt b/apps/emqx_gateway_mqttsn/test/emqx_sn_protocol_SUITE_data/ca.crt new file mode 100644 index 000000000..604fd2362 --- /dev/null +++ b/apps/emqx_gateway_mqttsn/test/emqx_sn_protocol_SUITE_data/ca.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDUTCCAjmgAwIBAgIJAPPYCjTmxdt/MA0GCSqGSIb3DQEBCwUAMD8xCzAJBgNV +BAYTAkNOMREwDwYDVQQIDAhoYW5nemhvdTEMMAoGA1UECgwDRU1RMQ8wDQYDVQQD +DAZSb290Q0EwHhcNMjAwNTA4MDgwNjUyWhcNMzAwNTA2MDgwNjUyWjA/MQswCQYD +VQQGEwJDTjERMA8GA1UECAwIaGFuZ3pob3UxDDAKBgNVBAoMA0VNUTEPMA0GA1UE +AwwGUm9vdENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzcgVLex1 +EZ9ON64EX8v+wcSjzOZpiEOsAOuSXOEN3wb8FKUxCdsGrsJYB7a5VM/Jot25Mod2 +juS3OBMg6r85k2TWjdxUoUs+HiUB/pP/ARaaW6VntpAEokpij/przWMPgJnBF3Ur +MjtbLayH9hGmpQrI5c2vmHQ2reRZnSFbY+2b8SXZ+3lZZgz9+BaQYWdQWfaUWEHZ +uDaNiViVO0OT8DRjCuiDp3yYDj3iLWbTA/gDL6Tf5XuHuEwcOQUrd+h0hyIphO8D +tsrsHZ14j4AWYLk1CPA6pq1HIUvEl2rANx2lVUNv+nt64K/Mr3RnVQd9s8bK+TXQ +KGHd2Lv/PALYuwIDAQABo1AwTjAdBgNVHQ4EFgQUGBmW+iDzxctWAWxmhgdlE8Pj +EbQwHwYDVR0jBBgwFoAUGBmW+iDzxctWAWxmhgdlE8PjEbQwDAYDVR0TBAUwAwEB +/zANBgkqhkiG9w0BAQsFAAOCAQEAGbhRUjpIred4cFAFJ7bbYD9hKu/yzWPWkMRa +ErlCKHmuYsYk+5d16JQhJaFy6MGXfLgo3KV2itl0d+OWNH0U9ULXcglTxy6+njo5 +CFqdUBPwN1jxhzo9yteDMKF4+AHIxbvCAJa17qcwUKR5MKNvv09C6pvQDJLzid7y +E2dkgSuggik3oa0427KvctFf8uhOV94RvEDyqvT5+pgNYZ2Yfga9pD/jjpoHEUlo +88IGU8/wJCx3Ds2yc8+oBg/ynxG8f/HmCC1ET6EHHoe2jlo8FpU/SgGtghS1YL30 +IWxNsPrUP+XsZpBJy/mvOhE5QXo6Y35zDqqj8tI7AGmAWu22jg== +-----END CERTIFICATE----- diff --git a/apps/emqx_gateway_mqttsn/test/emqx_sn_protocol_SUITE_data/dtls.server.crt b/apps/emqx_gateway_mqttsn/test/emqx_sn_protocol_SUITE_data/dtls.server.crt new file mode 100644 index 000000000..092390b1d --- /dev/null +++ b/apps/emqx_gateway_mqttsn/test/emqx_sn_protocol_SUITE_data/dtls.server.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDEzCCAfugAwIBAgIBAjANBgkqhkiG9w0BAQsFADA/MQswCQYDVQQGEwJDTjER +MA8GA1UECAwIaGFuZ3pob3UxDDAKBgNVBAoMA0VNUTEPMA0GA1UEAwwGUm9vdENB +MB4XDTIwMDUwODA4MDcwNVoXDTMwMDUwNjA4MDcwNVowPzELMAkGA1UEBhMCQ04x +ETAPBgNVBAgMCGhhbmd6aG91MQwwCgYDVQQKDANFTVExDzANBgNVBAMMBlNlcnZl +cjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALNeWT3pE+QFfiRJzKmn +AMUrWo3K2j/Tm3+Xnl6WLz67/0rcYrJbbKvS3uyRP/stXyXEKw9CepyQ1ViBVFkW +Aoy8qQEOWFDsZc/5UzhXUnb6LXr3qTkFEjNmhj+7uzv/lbBxlUG1NlYzSeOB6/RT +8zH/lhOeKhLnWYPXdXKsa1FL6ij4X8DeDO1kY7fvAGmBn/THh1uTpDizM4YmeI+7 +4dmayA5xXvARte5h4Vu5SIze7iC057N+vymToMk2Jgk+ZZFpyXrnq+yo6RaD3ANc +lrc4FbeUQZ5a5s5Sxgs9a0Y3WMG+7c5VnVXcbjBRz/aq2NtOnQQjikKKQA8GF080 +BQkCAwEAAaMaMBgwCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAwDQYJKoZIhvcNAQEL +BQADggEBAJefnMZpaRDHQSNUIEL3iwGXE9c6PmIsQVE2ustr+CakBp3TZ4l0enLt +iGMfEVFju69cO4oyokWv+hl5eCMkHBf14Kv51vj448jowYnF1zmzn7SEzm5Uzlsa +sqjtAprnLyof69WtLU1j5rYWBuFX86yOTwRAFNjm9fvhAcrEONBsQtqipBWkMROp +iUYMkRqbKcQMdwxov+lHBYKq9zbWRoqLROAn54SRqgQk6c15JdEfgOOjShbsOkIH +UhqcwRkQic7n1zwHVGVDgNIZVgmJ2IdIWBlPEC7oLrRrBD/X1iEEXtKab6p5o22n +KB5mN+iQaE+Oe2cpGKZJiJRdM+IqDDQ= +-----END CERTIFICATE----- diff --git a/apps/emqx_gateway_mqttsn/test/emqx_sn_protocol_SUITE_data/dtls.server.key b/apps/emqx_gateway_mqttsn/test/emqx_sn_protocol_SUITE_data/dtls.server.key new file mode 100644 index 000000000..6c338216e --- /dev/null +++ b/apps/emqx_gateway_mqttsn/test/emqx_sn_protocol_SUITE_data/dtls.server.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAs15ZPekT5AV+JEnMqacAxStajcraP9Obf5eeXpYvPrv/Stxi +sltsq9Le7JE/+y1fJcQrD0J6nJDVWIFUWRYCjLypAQ5YUOxlz/lTOFdSdvotevep +OQUSM2aGP7u7O/+VsHGVQbU2VjNJ44Hr9FPzMf+WE54qEudZg9d1cqxrUUvqKPhf +wN4M7WRjt+8AaYGf9MeHW5OkOLMzhiZ4j7vh2ZrIDnFe8BG17mHhW7lIjN7uILTn +s36/KZOgyTYmCT5lkWnJeuer7KjpFoPcA1yWtzgVt5RBnlrmzlLGCz1rRjdYwb7t +zlWdVdxuMFHP9qrY206dBCOKQopADwYXTzQFCQIDAQABAoIBAQCuvCbr7Pd3lvI/ +n7VFQG+7pHRe1VKwAxDkx2t8cYos7y/QWcm8Ptwqtw58HzPZGWYrgGMCRpzzkRSF +V9g3wP1S5Scu5C6dBu5YIGc157tqNGXB+SpdZddJQ4Nc6yGHXYERllT04ffBGc3N +WG/oYS/1cSteiSIrsDy/91FvGRCi7FPxH3wIgHssY/tw69s1Cfvaq5lr2NTFzxIG +xCvpJKEdSfVfS9I7LYiymVjst3IOR/w76/ZFY9cRa8ZtmQSWWsm0TUpRC1jdcbkm +ZoJptYWlP+gSwx/fpMYftrkJFGOJhHJHQhwxT5X/ajAISeqjjwkWSEJLwnHQd11C +Zy2+29lBAoGBANlEAIK4VxCqyPXNKfoOOi5dS64NfvyH4A1v2+KaHWc7lqaqPN49 +ezfN2n3X+KWx4cviDD914Yc2JQ1vVJjSaHci7yivocDo2OfZDmjBqzaMp/y+rX1R +/f3MmiTqMa468rjaxI9RRZu7vDgpTR+za1+OBCgMzjvAng8dJuN/5gjlAoGBANNY +uYPKtearBmkqdrSV7eTUe49Nhr0XotLaVBH37TCW0Xv9wjO2xmbm5Ga/DCtPIsBb +yPeYwX9FjoasuadUD7hRvbFu6dBa0HGLmkXRJZTcD7MEX2Lhu4BuC72yDLLFd0r+ +Ep9WP7F5iJyagYqIZtz+4uf7gBvUDdmvXz3sGr1VAoGAdXTD6eeKeiI6PlhKBztF +zOb3EQOO0SsLv3fnodu7ZaHbUgLaoTMPuB17r2jgrYM7FKQCBxTNdfGZmmfDjlLB +0xZ5wL8ibU30ZXL8zTlWPElST9sto4B+FYVVF/vcG9sWeUUb2ncPcJ/Po3UAktDG +jYQTTyuNGtSJHpad/YOZctkCgYBtWRaC7bq3of0rJGFOhdQT9SwItN/lrfj8hyHA +OjpqTV4NfPmhsAtu6j96OZaeQc+FHvgXwt06cE6Rt4RG4uNPRluTFgO7XYFDfitP +vCppnoIw6S5BBvHwPP+uIhUX2bsi/dm8vu8tb+gSvo4PkwtFhEr6I9HglBKmcmog +q6waEQKBgHyecFBeM6Ls11Cd64vborwJPAuxIW7HBAFj/BS99oeG4TjBx4Sz2dFd +rzUibJt4ndnHIvCN8JQkjNG14i9hJln+H3mRss8fbZ9vQdqG+2vOWADYSzzsNI55 +RFY7JjluKcVkp/zCDeUxTU3O6sS+v6/3VE11Cob6OYQx3lN5wrZ3 +-----END RSA PRIVATE KEY-----