3 분 소요

Redis를 캐시서버로 쓰고자 했을 때 SET이 되지 않았다. GET은 되는데 SET만 안되는 특이한 현상.

레디스 클라이언트 라이브러리 제작자가 첨부한 예제도 작동하지 않아서 C++에서 발생한 에러메시지를 살피던 중 다음과 같은 에러 메시지를 발견했다.

SET error: DENIED Redis is running in protected mode because protected mode is enabled, no bind address was specified, no authentication password is requested to clients. In this mode connections are only accepted from the loopback interface. If you want to connect from external computers to Redis you may adopt one of the following solutions: 1) Just disable protected mode sending the command ‘CONFIG SET protected-mode no’ from the loopback interface by connecting to Redis from the same host the server is running, however MAKE SURE Redis is not publicly accessible from internet if you do so. Use CONFIG REWRITE to make this change permanent. 2) Alternatively you can just disable the protected mode by editing the Redis configuration file, and setting the protected mode option to ‘no’, and then restarting the server. 3) If you started the server manually just for testing, restart it with the ‘–protected-mode no’ option. 4) Setup a bind address or an authentication password. NOTE: You only need to do one of the above things in order for the server to start accepting connections from the outside.

처음 보는 이 메시지에 당황해서 찾아보았다.

해결방법은 레디스 프로그램 파일에 첨부된 redis.conf 에 있었다. 이 파일에 보면 protected-mode 라는 환경설정 항목이 있고 이 항목의 값은 yes 로 되어 있다. 이 protected-mode 지시자가 무엇인지는 위에 주석에 자세히 써있다.

Protected mode is a layer of security protection, in order to avoid that

Redis instances left open on the internet are accessed and exploited.

#

When protected mode is on and if:

#

1) The server is not binding explicitly to a set of addresses using the

“bind” directive.

2) No password is configured.

#

The server only accepts connections from clients connecting from the

IPv4 and IPv6 loopback addresses 127.0.0.1 and ::1, and from Unix domain

sockets.

#

By default protected mode is enabled. You should disable it only if

you are sure you want clients from other hosts to connect to Redis

even if no authentication is configured, nor a specific set of interfaces

are explicitly listed using the “bind” directive.

대략적인 내용은 보호모드라는 항목이 있으며 이것은 인터넷을 통한 접속과 부당한 이용을 막기 위함이라고 한다. 이 보호모드를 다음과 같은 경우에 켜라고 한다. 서버가 bind 지시어를 통해 바인딩되어 있지 않은 경우, 암호가 설정되지 않은 경우.

2026년 수정 안내 원래 이 글의 결론은 “bind에 외부 IP를 지정하거나 protected-mode를 no로 바꾸면 된다”였다. 그런데 인용해둔 에러 메시지 안에 “MAKE SURE Redis is not publicly accessible from internet”이라는 경고가 있는데도 정작 결론에서 그 경고가 빠져 있었다. 인증 없이 노출된 Redis는 실제로 대규모 침해의 단골 경로다. 해결 방법을 우선순위대로 다시 정리한다.

해결 방법 (권장 순서)

1. 비밀번호를 설정한다 — 가장 권장

protected mode가 켜지는 조건 자체가 “bind도 없고 비밀번호도 없을 때”다. 비밀번호를 설정하면 protected mode를 끌 필요 없이 외부 접속이 열린다.

# redis.conf
requirepass 충분히__임의의_문자열

Redis 6 이상이라면 ACL로 사용자별 권한을 나누는 편이 더 낫다.

user gameserver on >비밀번호 ~cache:* +@read +@write

클라이언트에서는 접속 후 AUTH를 보내거나, 라이브러리의 password 옵션에 지정한다.

2. bind로 접근 인터페이스를 제한한다

Redis를 쓰는 서버가 정해져 있다면 그 인터페이스만 열어둔다.

bind 10.0.1.20 127.0.0.1

여기에 bind 0.0.0.0을 쓰면 안 된다. 모든 인터페이스에 열겠다는 뜻이라 사실상 protected mode를 끄는 것과 같다.

3. 방화벽과 네트워크로 막는다

위 두 가지와 별개로 반드시 함께 해야 한다. Redis 포트(6379)는 애플리케이션 서버에서만 접근 가능해야 한다.

# 특정 IP만 허용
firewall-cmd --permanent --add-rich-rule='rule family=ipv4 source address=10.0.1.0/24 port port=6379 protocol=tcp accept'

클라우드라면 보안 그룹으로 제한하는 것이 우선이다.

4. protected-mode를 끈다 — 마지막 수단

protected-mode no

위 1~3을 갖추지 않은 채 이것만 하면 안 된다. 인증 없이 인터넷에 노출된 Redis는 다음이 가능하다.

  • KEYS *로 전체 데이터 덤프
  • FLUSHALL로 전체 삭제
  • CONFIG SET dir + SAVE를 조합해 authorized_keys나 크론탭을 덮어쓰는 서버 장악

실제로 이 경로로 채굴 악성코드가 대량 유포된 사례가 여러 번 있었다. 개발 장비라도 공인 IP에 물려 있다면 예외가 아니다.

운영 환경이라면 위험한 명령 자체를 막아두는 것도 방법이다.

rename-command FLUSHALL ""
rename-command CONFIG ""

언제 생긴 설정인가

protected mode는 Redis 3.2.0에서 도입되었다. 2.8을 쓰던 시절에 없었던 것이 맞다.

댓글 남기기