우리의 서비스는 일요일마다 scheduler가 작동하여 redis에 특정 데이터를 저장하고, server가 해당 데이터를 redis에서 가져다 사용한다.
하지만 스케쥴러를 사용하여 redis에 데이터를 삽입해 주었는데, 다음날이 되면 redis의 데이터가 삭제되어 모두 사라져있는 경우가 한두번이 아니라 매일 발생하고 있었다.
1:S 19 Sep 2023 01:07:32.861 * Connecting to MASTER 120.77.210.109:60125
1:S 19 Sep 2023 01:07:32.861 * MASTER <-> REPLICA sync started
1:S 19 Sep 2023 01:07:32.862 * REPLICAOF 120.77.210.109:60125 enabled (user request from 'id=1957 addr=47.94.158.5:48330 laddr=192.168.48.2:6379 fd=11 name= age=3 idle=0 flags=N db=0 sub=0 psub=0 ssub=0 multi=-1 qbuf=30 qbuf-free=20444 argv-mem=26 multi-mem=0 rbs=1024 rbp=155 obl=0 oll=0 omem=0 tot-mem=22322 events=r cmd=slaveof user=default redir=-1 resp=2')
1:S 19 Sep 2023 01:07:33.118 # Error condition on socket for SYNC: Connection refused
1:S 19 Sep 2023 01:07:33.649 * Connecting to MASTER 120.77.210.109:60125
1:S 19 Sep 2023 01:07:33.649 * MASTER <-> REPLICA sync started
1:S 19 Sep 2023 01:07:33.903 # Error condition on socket for SYNC: Connection refused
1:S 19 Sep 2023 01:07:34.653 * Connecting to MASTER 120.77.210.109:60125
1:S 19 Sep 2023 01:07:34.654 * MASTER <-> REPLICA sync started
1:S 19 Sep 2023 01:07:34.907 # Error condition on socket for SYNC: Connection refused
1:S 19 Sep 2023 01:07:35.692 * Connecting to MASTER 120.77.210.109:60125
1:S 19 Sep 2023 01:07:35.692 * MASTER <-> REPLICA sync started
1:S 19 Sep 2023 01:07:35.950 # Error condition on socket for SYNC: Connection refused
1:S 19 Sep 2023 01:07:36.697 * Connecting to MASTER 120.77.210.109:60125
1:S 19 Sep 2023 01:07:36.697 * MASTER <-> REPLICA sync started
1:S 19 Sep 2023 01:07:36.955 # Error condition on socket for SYNC: Connection refused
1:S 19 Sep 2023 01:07:37.701 * Connecting to MASTER 120.77.210.109:60125
1:S 19 Sep 2023 01:07:37.701 * MASTER <-> REPLICA sync started
1:S 19 Sep 2023 01:07:37.957 # Error condition on socket for SYNC: Connection refused
1:M 19 Sep 2023 01:07:38.380 * Discarding previously cached master state.
1:M 19 Sep 2023 01:07:38.380 # Setting secondary replication ID to aa05b88d98c151625d9b0d867942fb14cacb11fe, valid up to offset: 1. New replication ID is 32dd01fdf5b93659fb06cf191fb3f261c4642aa4
1:M 19 Sep 2023 01:07:38.380 * MASTER MODE enabled (user request from 'id=1957 addr=47.94.158.5:48330 laddr=192.168.48.2:6379 fd=11 name= age=9 idle=0 flags=N db=0 sub=0 psub=0 ssub=0 multi=-1 qbuf=16 qbuf-free=20458 argv-mem=12 multi-mem=0 rbs=1024 rbp=223 obl=0 oll=0 omem=0 tot-mem=22308 events=r cmd=slaveof user=default redir=-1 resp=2')
1:S 19 Sep 2023 01:08:47.474 * Before turning into a replica, using my own master parameters to synthesize a cached master: I may be able to synchronize with the new master with just a partial transfer.
1:S 19 Sep 2023 01:08:47.474 * Connecting to MASTER 81.71.101.5:60131
1:S 19 Sep 2023 01:08:47.474 * MASTER <-> REPLICA sync started
1:S 19 Sep 2023 01:08:47.474 * REPLICAOF 81.71.101.5:60131 enabled (user request from 'id=1959 addr=47.94.158.5:49368 laddr=192.168.48.2:6379 fd=11 name= age=3 idle=0 flags=N db=0 sub=0 psub=0 ssub=0 multi=-1 qbuf=27 qbuf-free=20447 argv-mem=23 multi-mem=0 rbs=1024 rbp=155 obl=0 oll=0 omem=0 tot-mem=22319 events=r cmd=slaveof user=default redir=-1 resp=2')
1:M 19 Sep 2023 01:08:52.949 * Discarding previously cached master state.
1:M 19 Sep 2023 01:08:52.949 # Setting secondary replication ID to 32dd01fdf5b93659fb06cf191fb3f261c4642aa4, valid up to offset: 1. New replication ID is 752fb8b6bfc7d7b1d1d1af7da1af3cbcfe9d27ac
1:M 19 Sep 2023 01:08:52.949 * MASTER MODE enabled (user request from 'id=1959 addr=47.94.158.5:49368 laddr=192.168.48.2:6379 fd=11 name= age=8 idle=0 flags=N db=0 sub=0 psub=0 ssub=0 multi=-1 qbuf=16 qbuf-free=20458 argv-mem=12 multi-mem=0 rbs=1024 rbp=223 obl=0 oll=0 omem=0 tot-mem=22308 events=r cmd=slaveof user=default redir=-1 resp=2')
1:S 19 Sep 2023 01:09:58.618 * Before turning into a replica, using my own master parameters to synthesize a cached master: I may be able to synchronize with the new master with just a partial transfer.
1:S 19 Sep 2023 01:09:58.618 * Connecting to MASTER 153.0.195.243:60112
1:S 19 Sep 2023 01:09:58.619 * MASTER <-> REPLICA sync started
1:S 19 Sep 2023 01:09:58.619 * REPLICAOF 153.0.195.243:60112 enabled (user request from 'id=1961 addr=47.94.158.5:49616 laddr=192.168.48.2:6379 fd=11 name= age=3 idle=0 flags=N db=0 sub=0 psub=0 ssub=0 multi=-1 qbuf=29 qbuf-free=20445 argv-mem=25 multi-mem=0 rbs=1024 rbp=155 obl=0 oll=0 omem=0 tot-mem=22321 events=r cmd=slaveof user=default redir=-1 resp=2')
1:M 19 Sep 2023 01:10:04.636 * Discarding previously cached master state.
1:M 19 Sep 2023 01:10:04.637 # Setting secondary replication ID to 752fb8b6bfc7d7b1d1d1af7da1af3cbcfe9d27ac, valid up to offset: 1. New replication ID is 1131302c988fe147944ce744bc766a75f448332f
1:M 19 Sep 2023 01:10:04.637 * MASTER MODE enabled (user request from 'id=1961 addr=47.94.158.5:49616 laddr=192.168.48.2:6379 fd=11 name= age=9 idle=0 flags=N db=0 sub=0 psub=0 ssub=0 multi=-1 qbuf=16 qbuf-free=20458 argv-mem=12 multi-mem=0 rbs=1024 rbp=223 obl=0 oll=0 omem=0 tot-mem=22308 events=r cmd=slaveof user=default redir=-1 resp=2')
1:M 19 Sep 2023 02:07:31.082 * 1 changes in 3600 seconds. Saving...
1:M 19 Sep 2023 02:07:31.083 * Background saving started by pid 152
152:C 19 Sep 2023 02:07:31.087 * DB saved on disk
152:C 19 Sep 2023 02:07:31.088 * Fork CoW for RDB: current 0 MB, peak 0 MB, average 0 MB
1:M 19 Sep 2023 02:07:31.184 * Background saving terminated with success
로그를 확인해보니, 각기 다른 IP들에서 우리 서버의 redis slave-node로 만들려 하고 있는 것 같다. 그 결과 redis에서는 보안을 위해 데이터를 백업한 뒤 모두 지워버렸고 이 때문에 redis에서 데이터를 조회해도 아무런 데이터도 존재하지 않았던 것이다.
ufw allow 6379
처음에 redis를 우리의 서비스를 연결하고 실행하였을때, redis가 연결이 되지 않았다. 그래서 redis가 작동하고 있는 port에 대해 방화벽을 해제해주니 연결이 되었다.
기본적으로 대부분의 방화벽 설정은 허용되지 않은 트래픽을 차단하는 기본 드롭(DROP)
정책을 사용한다. 이는 내부에서의 접근과 외부에서의 접근을 모두 제한하는 것을 의미한다. 방화벽 규칙을 명시적으로 정의하지 않으면 모든 트래픽이 차단된다. 따라서 같은 서버에 존재하는 우리 서버가 redis에 접근을 할 수 없었던 것이다.
ufw deny 6379
먼저 redis가 작동하고 있는 6379 port에 대한 엑세스를 차단해주자.
이렇게 방화벽을 닫아주게 되면 당연히 외부에서는 우리 redis에 접근이 불가해지고, 우리 서버에서도 redis://xx.xx.xx.xx 이렇게 url을 통해 redis에 접근하고 있었기 때문에 우리 서버에서도 접근이 불가능해졌다. 이렇게 된 상황에서 서버와 레디스를 연결할 방법을 찾아야했다.
따라서 도커 네트워크를 이용하기로 하였다. 도커 네트워크를 사용하면 다른 컨테이너 간에 통신이 가능하다.
docker network create project_network
먼저 컨테이너들을 묶을 네트워크를 생성해 주었다.
docker network connect <network_name> <container_name_or_id>
그리고 redis와 우리의 서버 컨테이너를 project_network
에 포함시켜 주었다. 실행중인 컨테이너도 중지하지 않고 컨테이너에 연결할 수 있다.
REDIS_URL = redis://xx.xx.xx.xx:6379
->
REDIS_URL = redis://project_redis:6379
그리고 기존에 ip로 접근하던 우리의 redis 주소를 redis 컨테이너 이름으로 접근할 수 있게 바꾸어 주었다.
이제 도커 네트워크를 통해 컨테이너들끼리는 소통이 가능해지고, 외부에서는 우리 레디스에 접근할 수 없게 되었다. 이렇게 되면 당연히 작업할때 로컬에서도 redis에 접근이 불가하기 떄문에 개발환경과 실제환경 redis를 구분하여서 개발을 하여야 했다.
constructor() {
if (process.env.NODE_ENV === 'prod') {
this.client = createClient({
url: process.env.PROD_REDIS_URL,
});
} else {
this.client = createClient({
url: process.env.DEV_REDIS_URL,
});
}
this.client.on('connect', () => {
logger.info(`Redis Connected`);
});
}
이렇게 방화벽을 닫아서 개발을 할때, 서버에서 작동하고 있는 redis에 접근하지 못하니 개발용 redis를 하나 더 생성하고, 더욱더 개발환경과 배포 환경의 구분을 철저하게 해야 하는 점을 깨달았다.
위의 방법으로 수정하고 나서는 외부의 침입으로 인해 redis의 데이터가 모두 사라지는 현상은 발생하지 않았는데 발생하게 된다면 다시 포스팅하겠다.