원격 Mac에서 여러 차례 빌드를 수행하고 나면 개발 도구, 디버그 서버, 패키지 관리자, 임시 스크립트가 수신 포트를 남길 수 있습니다. 진짜 문제는 ‘포트가 많다’는 사실이 아니라 누가 수신 중인지, 어느 주소에 바인딩되어 있는지, Mac을 재시동한 뒤에도 다시 나타나는지를 답할 수 없다는 데 있습니다. 아래에서는 macOS 기본 도구만으로 반복 가능한 읽기 전용 감사 절차를 만든 다음, 네트워크 노출 범위를 단계적으로 줄입니다.
먼저 수신 포트 기준선 만들기
노드가 유휴 상태이고 임시 디버깅 작업이 실행되지 않을 때 TCP와 UDP 상태를 수집합니다. -nP를 사용하면 이름 조회와 포트 이름 변환을 생략할 수 있어 결과를 저장하고 비교하기가 더 쉽습니다.
mkdir -p "$HOME/audit/network"
stamp="$(date -u +%Y%m%dT%H%M%SZ)"
sudo lsof -nP -iTCP -sTCP:LISTEN \
> "$HOME/audit/network/tcp-$stamp.txt"
sudo lsof -nP -iUDP \
> "$HOME/audit/network/udp-$stamp.txt"
netstat -anv -p tcp \
> "$HOME/audit/network/netstat-tcp-$stamp.txt"
포트 번호만 확인해서는 안 됩니다. COMMAND, PID, USER, NAME을 함께 판단해야 합니다. 동일한 개발 서버라도 일반 사용자가 실행한 경우와 출처를 알 수 없는 프로그램이 root 권한으로 실행된 경우는 대응 우선순위가 완전히 다릅니다.
| 수신 형태 | 일반적인 의미 | 다음 단계 |
|---|---|---|
127.0.0.1:8080 |
IPv4 로컬 연결만 허용 | 예상된 개발 서비스인지 확인 |
[::1]:8080 |
IPv6 로컬 연결만 허용 | 유지한 뒤 SSH 포트 전달 테스트 |
*:8080 |
사용 가능한 모든 인터페이스에서 수신 | 프로세스를 확인하고 우선적으로 바인딩 축소 |
10.x.x.x:8080 |
특정 인터페이스에 바인딩 | 노드 네트워크 정책과 함께 검증 |
| 고정된 상대가 없는 UDP | 검색 또는 보조 서비스일 수 있음 | 프로세스 용도와 시작 원인 조사 |
LISTEN 상태라고 해서 반드시 외부에서 접근할 수 있는 것은 아닙니다. 최종 접근 가능 여부는 수신 주소, 호스트 방화벽, 노드 네트워크 정책이 함께 결정합니다. 다만 와일드카드 주소는 프로세스가 의도적으로 연결 수신 범위를 넓혔다는 뜻이므로 먼저 그 이유를 확인해야 합니다.
포트를 프로세스와 시작 항목까지 추적하기
PID를 찾았다면 ps로 전체 명령, 부모 프로세스, 실행 시간을 확인한 다음 상주 시작 항목에서 실행된 프로세스인지 조사합니다.
pid=1234
ps -p "$pid" -o pid,ppid,user,lstart,command
sudo lsof -nP -p "$pid"
launchctl print "gui/$(id -u)" > "$HOME/audit/network/launch-gui.txt"
sudo launchctl print system > "$HOME/audit/network/launch-system.txt"
find "$HOME/Library/LaunchAgents" \
/Library/LaunchAgents \
/Library/LaunchDaemons \
-maxdepth 1 -name '*.plist' -print 2>/dev/null
의심스러운 plist는 plutil -p 파일경로로 열어 Program, ProgramArguments, RunAtLoad, KeepAlive를 확인합니다. 빌드 스크립트가 임시로 시작한 프로세스라면 작업이 끝날 때 함께 종료되어야 합니다. KeepAlive 때문에 계속 재시작되는 경우에는 단순히 kill을 실행하는 것만으로 문제를 해결할 수 없습니다.
조치 목록 만들기
시스템 서비스가 아닌 수신 항목마다 최소한 서비스 용도, 담당자, 시작 방식, 바인딩 주소, 유지 사유를 기록합니다. 소유 관계를 확인할 수 없는 프로세스는 관련 작업부터 중지하고 명령줄, 로그 경로, plist 내용을 보존합니다. 파일을 즉시 삭제하면 조사에 필요한 맥락을 잃을 수 있습니다.
포트를 차단하기 전에 바인딩 주소부터 바꾸기
개발 서비스가 현재 사용자에게만 필요하다면 루프백 주소에 바인딩하는 것이 가장 직접적인 해결책입니다. 이렇게 하면 방화벽 규칙이 바뀌더라도 프로세스가 다른 인터페이스를 통한 연결을 능동적으로 수락하지 않습니다.
python3 -m http.server 8080 --bind 127.0.0.1
HOST=127.0.0.1 PORT=8080 ./run-development-server
자신의 컴퓨터에서 접속할 때는 SSH 로컬 포트 전달을 진입점으로 사용합니다.
ssh -N \
-L 127.0.0.1:9000:127.0.0.1:8080 \
"$REMOTE_USER@$REMOTE_HOST"
그런 다음 로컬의 127.0.0.1:9000으로 접속합니다. 이때 원격 서비스가 여전히 127.0.0.1:8080에서만 수신하는지 함께 확인해야 합니다. 시작 인수가 적용되지 않아 *:8080으로 되돌아가서는 안 됩니다.
바인딩 주소를 축소하는 방식은 차단 규칙을 새로 추가하는 것보다 대체로 검증하기 쉽고, 원격 관리 연결을 실수로 끊을 가능성도 낮습니다. 방화벽은 두 번째 방어 계층이며 올바른 서비스 수신 설정을 대신할 수 없습니다.
두 방화벽 계층을 읽기 전용으로 확인하기
macOS의 응용 프로그램 방화벽과 pf는 다루는 영역이 서로 다릅니다. 감사할 때는 먼저 상태만 조회하고 원격 세션에서 규칙을 바로 덮어쓰지 마십시오.
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstate
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --listapps
sudo pfctl -s info
sudo pfctl -sr
sudo pfctl -sn
응용 프로그램 방화벽 목록에서는 어떤 프로그램이 인바운드 연결을 수신하도록 허용되었는지 확인할 수 있습니다. pf 출력에서는 필터링과 주소 변환 규칙을 살펴볼 수 있습니다. 이상 항목을 발견하면 먼저 전체 출력을 저장한 뒤 해당 규칙이 시스템 구성, 운영 절차, 임시 실험 중 어디에서 비롯되었는지 확인합니다.
pf를 원격으로 수정할 때 가장 큰 위험은 구문 오류가 아니라 현재 관리 연결까지 차단하는 것입니다. 검증된 두 번째 연결 경로가 없다면 읽기 전용 점검에서 멈춰야 합니다. 반드시 변경해야 한다면 먼저 규칙을 백업하고 롤백 명령을 명확히 준비한 다음, 별도의 세션에서 콘솔 접근 가능 여부를 계속 확인해야 합니다.
차이 비교로 포트 재발 방지하기
한 번의 정리만으로는 이후의 도구 업그레이드, 빌드 스크립트 변경, 새 시작 항목까지 대응할 수 없습니다. 환경 초기화가 끝나면 승인된 기준선을 저장하고, 큰 변경이 있을 때마다 상태를 다시 수집하는 것이 좋습니다.
latest_tcp="$(ls -t "$HOME"/audit/network/tcp-*.txt | head -n 1)"
diff -u "$HOME/audit/network/tcp-approved.txt" "$latest_tcp"
latest_udp="$(ls -t "$HOME"/audit/network/udp-*.txt | head -n 1)"
diff -u "$HOME/audit/network/udp-approved.txt" "$latest_udp"
차이 비교에서 새 항목이 나타나면 정해진 순서에 따라 확인합니다. 프로세스의 소유 관계를 파악하고, 수신 주소와 시작 원인을 확인하며, 원격 접근이 필요한지 판단한 뒤에야 유지할지, 로컬 바인딩으로 바꿀지, 비활성화할지를 결정합니다. 포트 번호를 정적 허용 목록에 추가한 뒤 추적을 중단해서는 안 됩니다. 같은 포트를 나중에 다른 프로그램이 차지할 수 있기 때문입니다.
OwnAMac의 전용 물리 노드에서도 이 절차를 빌드 에이전트, 미리보기 서버, 테스트 콜백 프로세스, 임시 파일 서비스에 동일하게 적용할 수 있습니다. 작업을 마친 뒤 원본 스냅샷, 조치 기록, 재점검 결과를 보관하면 다음 환경 변경 때 현재 상태를 처음부터 추측하지 않고 차이점부터 조사할 수 있습니다.
자주 묻는 질문
LISTEN 상태인 포트는 인터넷에서 바로 접근할 수 있나요?
반드시 그렇지는 않습니다. 수신 주소, 네트워크 정책, 방화벽 규칙을 함께 확인해야 합니다. 127.0.0.1 또는 ::1에 바인딩된 서비스는 일반적으로 로컬 전용이며, * 또는 인터페이스 주소는 외부 검증이 필요합니다.
원격 감사 중에 pf 규칙을 바로 변경해도 되나요?
검증된 복구 경로가 있을 때만 권장합니다. 현재 규칙과 수신 목록을 먼저 저장하고 별도의 관리 세션을 유지한 상태에서 작은 변경만 시험해야 합니다. 복구 경로가 없다면 읽기 전용으로 점검합니다.
localhost에만 바인딩한 서비스는 로컬 컴퓨터에서 어떻게 접속하나요?
SSH 로컬 포트 전달을 사용합니다. 로컬 컴퓨터의 포트를 원격 127.0.0.1 서비스에 연결하면 개발 서비스를 모든 네트워크 인터페이스에 공개하지 않고도 접근할 수 있습니다.
다음 빌드를 독점 Apple Silicon 물리 노드에서 실행하세요
작업 규모에 따라 세 가지 구성과 다섯 개 노드 중에서 선택할 수 있으며, 컴퓨팅과 스토리지는 다른 테넌트와 공유되지 않습니다. 모든 노드는 연중 365일 정상 운영되며, 실제 사용 가능 상태는 콘솔의 실시간 응답을 기준으로 합니다.