Skip to content
isdnetworks
Go back

로컬에서만 붙던 서비스

서비스를 두 대로 나누면서 저장소를 다른 장비로 뺐다. 붙질 않았다.

Table of contents

Open Table of contents

증상 — 붙질 않았다

돌아온 것은 이 한 줄이었다.

Connection refused

Connection refused 를 보고 방화벽을 먼저 의심했는데 그쪽은 열려 있었다.

전에는 같은 장비 안에 있었으니 아무 문제가 없었고 장비를 나누면서 무엇이 달라졌는지를 찾아야 했다.

원인 — 어디에 붙어 있는지 봤다

ss 로 듣고 있는 주소를 봤다.

$ ss -lntp | grep 6379
LISTEN 0 128 127.0.0.1:6379 0.0.0.0:*  users:(("redis-server",pid=1841,...))

127.0.0.1:6379 라 그 장비 안에서만 붙는다.

방화벽을 다 열어도 밖에서는 못 붙고 0.0.0.0:6379 였다면 모든 주소에서 받았을 텐데 지금은 아니었다.

같은 장비 안에 있을 때는 127.0.0.1 로 충분했고 장비를 나누는 작업에 bind 를 다시 정하는 일이 딸려 있다는 것을 몰랐다.

비교 — 거부와 시간 초과

Connection refused 라는 메시지가 이미 답을 가리키고 있었다.

Connection refused    → 아무도 안 듣고 있다
Connection timed out  → 듣고는 있는데 중간에 막혔다

refused 는 그 주소와 포트에 닿았는데 받는 쪽이 없다는 뜻이다.

방화벽이 DROP 하면 대개 응답 없이 timed out 이 되고 두 신호를 구분하지 않으면 방화벽만 계속 뒤지게 된다.

메시지가 어느 쪽인지 먼저 봤어야 했다. 그 한 줄이 조사 방향을 정하고 있었다.

조치 — 필요한 주소만 열기

전부 여는 대신 필요한 주소만 적었다.

bind 127.0.0.1 10.0.0.31

bind 에 적은 두 주소만 듣고 0.0.0.0 으로 두면 공인 주소에서도 받는다.

주소를 지정하면 그 주소가 장비에 붙어 있어야 뜬다.

# 주소가 아직 안 붙었을 때
Warning: Could not create server TCP listening socket 10.0.0.31:6379: bind: Cannot assign requested address

부팅 순서에 걸리므로 network-online.target 뒤에 뜨게 했다.

# /etc/systemd/system/redis.service.d/override.conf
[Unit]
After=network-online.target
Wants=network-online.target

좁게 여는 대신 뜨는 조건이 하나 늘어난 셈이다.

설정 — 인증과 위험한 명령

로컬에서만 듣던 동안은 인증이 없었다.

requirepass <값>

밖에서 붙게 되면 그 제약이 사라지므로 requirepass 를 켰다.

$ chmod 600 /etc/redis/redis.conf
$ chown redis:redis /etc/redis/redis.conf

값을 설정 파일에 두고 파일 권한을 좁혔으며 애플리케이션 쪽은 코드가 아니라 환경에서 읽게 했다.

붙을 수 있게 되면 붙어서 할 수 있는 것도 는다.

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

rename-command 로 이름을 비워 운영에서 쓸 일 없는 것을 없앴다.

CONFIG 를 막으면 운영 중에 설정을 못 바꾼다. 그것이 불편한지 위험한지를 재고 설정은 파일로 바꾸고 재시작하기로 정했다.

검증 — 순서와 양쪽 확인

듣는 주소를 정한 뒤에 들어올 곳을 정했다.

$ iptables -A INPUT -p tcp --dport 6379 -s 10.0.0.32 -j ACCEPT
$ iptables -A INPUT -p tcp --dport 6379 -j DROP

10.0.0.32 에서만 받고 나머지는 끊는다.

순서가 있다. 듣는 주소를 좁히는 것이 먼저고 방화벽이 나중이라 반대로 하면 방화벽 규칙 하나가 잘못됐을 때 그대로 열린다.

확인은 양쪽에서 했다.

# 애플리케이션 서버에서
$ nc -vz -w 3 10.0.0.31 6379
Connection to 10.0.0.31 6379 port [tcp/*] succeeded!

# 다른 장비에서
$ nc -vz -w 3 10.0.0.31 6379
nc: connect to 10.0.0.31 port 6379 (tcp) failed: Connection timed out

nc 로 보니 붙어야 할 곳에서 붙고 안 붙어야 할 곳에서 안 붙는다.

앞만 보면 열려 있으면 안 되는 경로가 열린 것을 못 본다.

$ redis-cli -h 10.0.0.31 ping
(error) NOAUTH Authentication required.

인증이 실제로 걸렸는지도 같은 방식으로 확인했다.

정리


Share this post on:

Previous Post
중간 역할은 어느 쪽에도 없다
Next Post
규칙이 시점에 따라 달랐다