Skip to content

Commit 93b90c7

Browse files
ansdmergify[bot]
authored andcommitted
Close MQTT connection with delay when authentication fails
For consistency with other protocols (to protect from potential DoS attacks). Wrong credentials and virtual host access errors trigger the delay. References #11831 We keep the delay low when running tests. Otherwise, ``` make -C deps/rabbitmq_mqtt ct-auth ``` would run 3 minutes longer (with a SILENT_CLOSE_DELAY of 3 seconds). (cherry picked from commit 80ff6d0) (cherry picked from commit 9e84378)
1 parent 1e3f3e5 commit 93b90c7

File tree

1 file changed

+17
-10
lines changed

1 file changed

+17
-10
lines changed

deps/rabbitmq_mqtt/src/rabbit_mqtt_processor.erl

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@
4242
-define(QUEUE_TTL_KEY, <<"x-expires">>).
4343
-define(DEFAULT_EXCHANGE_NAME, <<>>).
4444

45+
-ifdef(TEST).
46+
-define(SILENT_CLOSE_DELAY, 10).
47+
-else.
48+
-define(SILENT_CLOSE_DELAY, 3_000).
49+
-endif.
50+
4551
-type send_fun() :: fun((iodata()) -> ok).
4652
-type session_expiry_interval() :: non_neg_integer() | infinity.
4753
-type subscriptions() :: #{topic_filter() => #mqtt_subscription_opts{}}.
@@ -643,16 +649,16 @@ check_extended_auth(_) ->
643649
check_credentials(Username, Password, SslLoginName, PeerIp) ->
644650
case creds(Username, Password, SslLoginName) of
645651
nocreds ->
646-
auth_attempt_failed(PeerIp, <<>>),
647652
?LOG_ERROR("MQTT login failed: no credentials provided"),
653+
auth_attempt_failed(PeerIp, <<>>),
648654
{error, ?RC_BAD_USER_NAME_OR_PASSWORD};
649655
{invalid_creds, {undefined, Pass}} when is_binary(Pass) ->
650-
auth_attempt_failed(PeerIp, <<>>),
651656
?LOG_ERROR("MQTT login failed: no username is provided"),
657+
auth_attempt_failed(PeerIp, <<>>),
652658
{error, ?RC_BAD_USER_NAME_OR_PASSWORD};
653659
{invalid_creds, {User, _Pass}} when is_binary(User) ->
654-
auth_attempt_failed(PeerIp, User),
655660
?LOG_ERROR("MQTT login failed for user '~s': no password provided", [User]),
661+
auth_attempt_failed(PeerIp, User),
656662
{error, ?RC_BAD_USER_NAME_OR_PASSWORD};
657663
{UserBin, PassBin} ->
658664
{ok, {UserBin, PassBin}}
@@ -1038,8 +1044,8 @@ check_vhost_exists(VHost, Username, PeerIp) ->
10381044
true ->
10391045
ok;
10401046
false ->
1041-
auth_attempt_failed(PeerIp, Username),
10421047
?LOG_ERROR("MQTT connection failed: virtual host '~s' does not exist", [VHost]),
1048+
auth_attempt_failed(PeerIp, Username),
10431049
{error, ?RC_BAD_USER_NAME_OR_PASSWORD}
10441050
end.
10451051

@@ -1078,10 +1084,10 @@ check_user_login(VHost, Username, Password, ClientId, PeerIp, ConnName) ->
10781084
notify_auth_result(user_authentication_success, Username1, ConnName),
10791085
{ok, User};
10801086
{refused, Username, Msg, Args} ->
1081-
auth_attempt_failed(PeerIp, Username),
10821087
?LOG_ERROR("MQTT connection failed: access refused for user '~s':" ++ Msg,
10831088
[Username | Args]),
10841089
notify_auth_result(user_authentication_failure, Username, ConnName),
1090+
auth_attempt_failed(PeerIp, Username),
10851091
{error, ?RC_BAD_USER_NAME_OR_PASSWORD}
10861092
end.
10871093

@@ -1110,9 +1116,9 @@ check_vhost_access(VHost, User = #user{username = Username}, ClientId, PeerIp) -
11101116
ok ->
11111117
{ok, AuthzCtx}
11121118
catch exit:#amqp_error{name = not_allowed} ->
1113-
auth_attempt_failed(PeerIp, Username),
11141119
?LOG_ERROR("MQTT connection failed: access refused for user '~s' to vhost '~s'",
11151120
[Username, VHost]),
1121+
auth_attempt_failed(PeerIp, Username),
11161122
{error, ?RC_NOT_AUTHORIZED}
11171123
end.
11181124

@@ -1121,9 +1127,9 @@ check_user_loopback(Username, PeerIp) ->
11211127
ok ->
11221128
ok;
11231129
not_allowed ->
1130+
?LOG_WARNING("MQTT login failed: user '~s' can only connect via localhost",
1131+
[Username]),
11241132
auth_attempt_failed(PeerIp, Username),
1125-
?LOG_WARNING(
1126-
"MQTT login failed: user '~s' can only connect via localhost", [Username]),
11271133
{error, ?RC_NOT_AUTHORIZED}
11281134
end.
11291135

@@ -1142,8 +1148,8 @@ ensure_credential_expiry_timer(User = #user{username = Username}, PeerIp) ->
11421148
_TimerRef = erlang:send_after(Time, self(), credential_expired),
11431149
ok;
11441150
false ->
1145-
auth_attempt_failed(PeerIp, Username),
11461151
?LOG_WARNING("Credential expired ~b ms ago", [abs(Time)]),
1152+
auth_attempt_failed(PeerIp, Username),
11471153
{error, ?RC_NOT_AUTHORIZED}
11481154
end
11491155
end.
@@ -1262,7 +1268,8 @@ creds(User, Pass, SSLLoginName) ->
12621268

12631269
-spec auth_attempt_failed(inet:ip_address(), binary()) -> ok.
12641270
auth_attempt_failed(PeerIp, Username) ->
1265-
rabbit_core_metrics:auth_attempt_failed(PeerIp, Username, mqtt).
1271+
rabbit_core_metrics:auth_attempt_failed(PeerIp, Username, mqtt),
1272+
timer:sleep(?SILENT_CLOSE_DELAY).
12661273

12671274
maybe_downgrade_qos(?QOS_0) -> ?QOS_0;
12681275
maybe_downgrade_qos(?QOS_1) -> ?QOS_1;

0 commit comments

Comments
 (0)