Skip to content
isdnetworks
Go back

포트 번호를 매번 찾고 있었다

게임 서버가 여러 개 떠 있는데 각각 포트가 다르다. 어느 것이 몇 번인지 매번 문서를 찾았는데 그 문서도 실제와 달랐다.

Table of contents

Open Table of contents

실제로 무엇이 떠 있나

문서 대신 서버에서 직접 봤다.

$ netstat -tlnp | grep LISTEN
tcp  0.0.0.0:8080   java   (웹)
tcp  0.0.0.0:9001   game   (게임 1)
tcp  0.0.0.0:9002   game   (게임 2)
tcp  0.0.0.0:9100   game   (게임 3?)
tcp  0.0.0.0:7777   chat
tcp  0.0.0.0:12000  admin

netstat -tlnp 로 지금 듣고 있는 포트와 그것을 쓰는 프로세스를 함께 뽑았다. ss -tlnp 도 같은 것을 준다.

9001과 9002는 규칙이 보이는데 9100이 튄다. 7777과 12000은 왜 그 번호인지 모르겠어서 물어보니 각자 만들 때 비어 있는 번호를 골랐다고 했다.

뽑아 보니 문서에 없는 것도 있고 문서에는 있는데 안 떠 있는 것도 있었다. 문서는 어느 시점의 상태를 적어 둔 것이고 그 뒤로 갱신되지 않은 것이었다.

규칙을 정했다

새로 만들 것부터 규칙을 적용하기로 했다.

90xx   게임 서버      9001, 9002, ...
91xx   게임 서버(개발) 9101, 9102, ...  (운영 + 100)
80xx   웹             8001, 8002
81xx   웹(개발)        8101, 8102
70xx   보조 서비스     7001(채팅), 7002(랭킹)
71xx   보조(개발)

개발용은 운영 번호에 100을 더한다. 운영이 9001이면 개발은 9101이고 그러면 개발 서버의 포트를 안 찾아도 운영 번호에서 계산된다.

대역을 고를 때 걸리는 것이 하나 있었다. 커널이 나가는 연결에 임시로 쓰는 포트 범위가 따로 있는데 리눅스에서는 sysctlnet.ipv4.ip_local_port_range 가 그것을 정한다. 그 안에 서비스 포트를 두면 서버를 띄우기 전에 그 번호가 임시로 잡혀 있을 수 있고 그러면 기동이 실패하므로 대역을 그 범위 밖으로 잡았다.

옮길지 남길지의 판단

이미 도는 것들을 옮기는 것은 다른 문제였다. 포트를 바꾸면 iptables 설정과 클라이언트 설정과 감시 설정을 다 고쳐야 하고 중단 없이 하려면 두 포트를 동시에 열어야 한다.

옮기는 것과 남기는 것을 갈랐다.

서비스판단
게임 3 (9100)옮김 — 규칙에 가깝고 영향 적음
채팅 (7777)남김 — 클라이언트 배포 필요
관리자 (12000)옮김 — 내부용이라 영향 적음

전부 옮기는 것이 깔끔하지만 값보다 비용이 컸다. 남기는 것은 예외로 문서에 적었는데 예외를 적어 두지 않으면 다음 사람이 규칙이 안 지켜진 것으로 보고 다시 검토한다.

문서를 실제에서 만들었다

손으로 적은 문서는 낡으므로 서버에서 뽑아 만들게 했다.

#!/bin/sh
for h in game-01 game-02 web-01; do
  echo "=== $h ==="
  ssh "$h" "netstat -tlnp 2>/dev/null | awk '/LISTEN/ {print \$4, \$7}'"
done

ssh 로 각 호스트의 netstat 출력을 awk 로 추려 모으고 이것을 crontab 으로 돌려 결과를 문서에 붙였다. 실제와 다를 수가 없다.

돌려 보니 문서에 없던 것이 두 개 나왔다. 누가 시험용으로 띄워 놓고 안 내린 것이었다.

검증 — 충돌 확인과 방화벽

새 서비스를 띄울 때 그 포트가 비어 있는지 확인하는 것을 시작 스크립트에 넣었다.

PORT=9003
if netstat -tln | grep -q ":${PORT} "; then
  echo "포트 ${PORT} 가 이미 사용 중입니다"
  netstat -tlnp | grep ":${PORT} "
  exit 1
fi

이미 쓰는 프로세스까지 보여 주니 그냥 실패보다 다음 행동이 정해진다. lsof -i :포트 로도 같은 것을 본다.

이 확인이 없으면 더 나쁜 일이 난다. 포트를 잡는 서버는 bindEADDRINUSE 로 실패했을 때 그 자리에서 끝나지 않고 다음 번호로 올라가는 것이 많아서 기동이 언제나 성공으로 보이고 그대로 쌓인다.

포트 규칙이 생기니 방화벽 설정도 단순해졌다.

90xx  게임 클라이언트 대역에서 허용
91xx  사내 대역에서만 허용
80xx  전체 허용 (앞단 경유)

개별 포트를 하나씩 여는 대신 iptables 에서 범위로 처리한다. 새 게임 서버를 띄울 때 방화벽을 안 건드려도 된다.

규칙이 있으면 그 규칙 위에 다른 것을 얹을 수 있다. 번호가 제각각이면 매번 개별 설정이다.

정리


Share this post on:

Previous Post
파일 하나에 프로세스 하나를 띄우고 있었다
Next Post
거래소가 약한 자리였다