최근에 자주 다음 질문을 받는 케이스가 늘어서 정리합니다.(사실 저도 당한…)
최신 버전 3.2.x 을 설치하고 클라이언트를 접속하고 보면… 접속이 안됩니다.
일단 client 로 접속을 하게 되면 다음과 같은 에러를 볼 수 있습니다.
(항상이 아니라 흔히 볼 수 있습니다.)
“-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.\r\n”;
이유가 무엇인고 하면 3.2.x 부터 Redis 에 Protected mode 라는 것이 생겼습니다. 이 Protected Mode라는 것은 또 무엇인고 하니, 혹시 예전의 보안 사고를 기억하시나요? Redis 는 굉장히 보안에 취약합니다. 특히 public 으로 열어두면 거의 해킹의 온상이 되는… 방법은 그렇게 공개하지는 않겠습니다.
그래서 추가된 것이 이 protected mode 입니다. protected mode 가 설정되어 있는 상태에서 패스워드가 설정되지 않고, 특정 ip로 bind가 되어있지 않으면, connection 자체가 위의 에러를 내면서 실패하게 됩니다.
그런데 이런 문의가 급증하는 것은 이 protected mode 가 default yes 이고 보통 특정 ip로 bind 시키지 않고 requirepass 를 지정하지 않습니다. 보통은 내부망에서만 쓰라는 얘기가 되는거죠. 그래서 이걸 해결 하기 위해서는 다음 명령을 127.0.0.1 즉 local loopback 주소에서 접속한 다음 날려야 합니다.
config set protected-mode no
실제 코드를 보면 다음 부분에서 문제가 되는겁니다. src/networking.c 에 있습니다.
if (server.protected_mode && server.bindaddr_count == 0 && server.requirepass == NULL && !(flags & CLIENT_UNIX_SOCKET) && ip != NULL) { if (strcmp(ip,"127.0.0.1") && strcmp(ip,"::1")) { char *err = "-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.\r\n"; if (write(c->fd,err,strlen(err)) == -1) { /* Nothing to do, Just to avoid the warning... */ } server.stat_rejected_conn++; freeClient(c); return; } }
점점 보안이 중요해지네요. 제 acl 패치는 언제 받아들여질지 T.T