[MySQL] DB 연결 host is blocked because of many connection errors
DB에 연결하려는데 갑자기 블락 알림창 뜨면서 연결할 수 없었다.
"Host {아이피} is blocked because of many connection errors"
[해결]
RDS DB 재시작 하면 초기화 된다고 하지만 함부로 할 수 없다.
1. max_connect_errors 조회
SHOW VARIABLES LIKE 'max_connect_errors';
하지만 DB에 붙을 수가 있어야 쿼리를 날리니까...
내 PC에서는 확인할 수가 없어서 다른 PC에서 실행해봤다.
AWS 콘솔에서도 확인은 할 수 있다.
- RDS 데이터베이스 선택 > 구성 > 파라미터 그룹 선택 > 'max_connect_errors'
'-' 로 되어 있는 건 설정을 안 했다는 뜻이다.
그래서 기본값인 100으로 설정된 상황이다.
- MySQL 공식 문서에서 기본값 확인 가능 https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_max_connect_errors
2. 호스트 캐시 초기화
-> 연속된 연결 오류 수 초기화
-> 호스트 차단 해제
FLUSH HOSTS;
근데 루트에서 실행해야 됨.
RELOAD 권한 없다고 에러 뜸.
SQL Error [1227] [42000]: Access denied; you need (at least one of) the RELOAD privilege(s) for this operation
방금은 RDS DB에 따로 설치한 DB를 연결해서 저 쿼리를 실행했었다.
다시 루트 DB에 연결해서 쿼리 실행해야 한다.
'FLUSH HOSTS' is deprecated and will be removed in a future release. Please use TRUNCATE TABLE performance_schema.host_cache instead
초기화가 되긴 됐는데 안내 메시지가 출력된다.
FLUSH HOSTS는 deprecated 되었기 때문에 MySQL 8.0.23 이상에서는 TRUNCATE를 사용하여 호스트 캐시를 초기화 하라고 한다.
TRUNCATE TABLE performance_schema.host_cache;
[원인 분석]
그럼 도대체 내 IP가 왜 차단되었을까..?
1. 호스트 캐시 확인
SELECT * FROM performance_schema.host_cache;
호스트별 에러 횟수를 확인할 수 있는 테이블이다.
예를 들어서, DB 연결할 때 비밀번호를 틀리면 COUNT_AUTHENTICATION_ERRORS 카운트가 올라간다.
그런데 이번 블락 원인은 핸드쉐이크 오류였다.
- COUNT_HANDSHAKE_ERRORS : MySQL의 Handshake 프로토콜이 완료되지 않았을 때 증가
2. MySQL에 TCP연결 시 핸드쉐이크 오류 발생
알고보니까 DB 작업을 하면서 연결이 얼마나 오래 끊기는지 간단하게 확인하려고 만든 스크립트가 문제였다.
nc 명령어를 이용해서 1초 간격으로 TCP 연결을 확인하는 스크립트였는데,
TCP 연결 후 핸드쉐이크 프로토콜을 완료하지 않아서 mysql이 핸드쉐이크 오류로 카운팅 해버리는 것이다.
즉, MySQL DB에 단순히 TCP 연결만 하고 넘어가면 오류가 발생한다.
(MySQL 버그 보고 : https://bugs.mysql.com/bug.php?id=93197)
3. 연속된 연결 오류 수가 max_connect_errors 초과하면 호스트 차단
호스트 캐시 테이블 보니까 COUNT_HANDSHAKE_ERRORS 증가할 때 SUM_CONNECT_ERRORS 값이 증가했다.
- SUM_CONNECT_ERRORS : 차단으로 간주되는 연결 오류 수
→ 이 값이 max_connect_errors 초과하면 호스트가 차단된다.
그런데 연결 성공하면 SUM_CONNECT_ERRORS가 0으로 초기화 되었다.
찾아보니까 항상 초기화되지는 않는다고 한다.
결론
연속해서 많은 TCP 연결을 시도하지 않도록 주의해야 하고,
필요한 경우 max_connect_errors 값을 크게 설정하면 되지만,
mysql에 TCP 연결은 웬만하면 하지 말 것..