공공부하자개발 · 영어 학습 노트
리눅스
리눅스 운영RHEL 에서 배포·운영하기0/13 완료
  • 01셸 기본과 파일 시스템
  • 02텍스트 처리 (grep·sed·awk)
  • 03프로세스·서비스 관리 (systemd)
  • 04자바 애플리케이션 배포
  • 05Tomcat·nginx 배포·재기동
  • 06로그·디스크 운영 (logrotate·cron)
  • 07네트워크 진단 (ss·curl·firewalld)
  • 08셸 스크립트 (운영 자동화)
  • 09장애 대응 (jstack·jmap·OOM killer·FD)
  • 10보안 기초 (ssh 강화·SELinux·감사 로그)
  • 11컨테이너 기초 (podman)
  • 12백업·복구 (설정·릴리스·DB 덤프)
  • 13Docker 실무
사이트 소개개인정보처리방침연락처
© 2026 공부하자
홈 › 리눅스 운영 › 07 / 13

네트워크 진단 (ss·curl·firewalld)

섹션 7진행 0 / 13
1왜 배우는가2핵심 원리3코드 예제4응용 변형 예제5자주 하는 실수 (Tip)6연습 문제7정리‹ 이전다음 ›

2. 핵심 원리

2.1 다섯 단계 진단 순서

연결 문제는 안쪽부터 바깥쪽으로 확인합니다. 각 단계가 통과해야 다음으로 갑니다.

단계 질문 명령
1 앱이 포트를 듣는가 ss -ltnp
2 서버 안에서 응답하는가 curl localhost:8080
3 방화벽이 여는가 firewall-cmd --list-ports
4 다른 서버에서 닿는가 nc -zv 서버 8080
5 이름이 풀리는가 getent hosts 이름

1·2 가 실패면 앱 문제, 3 이 실패면 방화벽, 4 만 실패면 중간 네트워크 장비, 5 가 실패면 DNS 입니다.

2.2 ss 로 포트 보기

ss 는 netstat 의 후속으로 RHEL 기본입니다. 옵션 네 개를 묶어 외웁니다.

옵션 뜻
-l 듣는 소켓만
-t TCP
-n 이름 대신 숫자
-p 프로세스 표시
bash
ss -ltnp | grep :8080               # LISTEN 0 128 *:8080 users:(("java",pid=1234))
ss -tnp state established | grep :1521   # DB 로 맺힌 연결
ss -s                               # TCP 요약, TIME-WAIT 수

*:8080 이면 모든 IP 에서 받고 127.0.0.1:8080 이면 서버 안에서만 받습니다. 밖에서 안 열리는 흔한 원인이 이 바인드 주소입니다.

2.3 curl 기본 옵션

옵션 뜻
-s 진행 표시 끔
-o /dev/null 본문 버림
-w '%{http_code}' 상태 코드 출력
-I 헤더만
-f 4xx·5xx 면 실패 코드
-m 5 전체 5초 제한
--connect-timeout 2 연결만 2초 제한
-v 요청·응답 전부

curl -s -o /dev/null -w '%{http_code}\n' URL 이 스크립트에서 가장 많이 쓰는 형태입니다. 200 이면 정상, 000 이면 연결 자체가 안 된 것입니다.

2.4 curl 종료 코드

-f 를 쓰면 HTTP 실패가 종료 코드로 나옵니다. 코드로 원인이 나뉩니다.

코드 뜻 원인
0 성공
6 이름 못 풀음 DNS
7 연결 실패 포트 닫힘·방화벽
22 HTTP 4xx·5xx 앱 오류
28 타임아웃 느림·방화벽 DROP
35·60 TLS 실패 인증서

7 은 즉시 거부된 것이고 28 은 응답이 없는 것입니다. 방화벽이 REJECT 면 7, DROP 이면 28 이 나옵니다. Windows 의 Git Bash 는 거부도 28 로 나올 수 있습니다.

2.5 응답 시간 분해

-w 로 단계별 시간을 뽑으면 느린 곳이 DNS 인지 연결인지 앱인지 갈립니다.

bash
curl -s -o /dev/null -w 'dns=%{time_namelookup} connect=%{time_connect} first=%{time_starttransfer} total=%{time_total}\n' URL

connect 가 크면 네트워크, first 에서 connect 를 뺀 값이 크면 앱이 느린 것입니다. 실무에서는 이 한 줄을 스크립트로 두고 배포 전후에 비교합니다.

2.6 POST 와 헤더

API 를 서버에서 직접 호출할 때의 형태입니다. 브라우저 없이 백엔드만 검증합니다.

bash
curl -s -X POST -H 'Content-Type: application/json' -d '{"id":1}' URL
curl -s -H 'Authorization: Bearer TOKEN' URL
curl -sv URL 2>&1 | grep -E '^(> |< )'     # 요청은 >, 응답은 <

-v 출력은 표준 에러로 나오므로 2>&1 로 합쳐야 grep 이 됩니다. > 줄이 보낸 헤더, < 줄이 받은 헤더입니다.

2.7 포트 열림 확인: nc 와 /dev/tcp

상대 서버의 포트에 TCP 연결이 되는지만 봅니다. HTTP 가 아닌 DB·Redis 포트도 됩니다.

bash
nc -zv db-prod 1521                 # Connected 또는 Connection refused
timeout 3 bash -c '</dev/tcp/db-prod/1521' && echo open || echo closed

nc 가 없는 서버에서는 bash 내장 /dev/tcp 를 씁니다. timeout 3 을 앞에 붙여야 DROP 방화벽에서 무한히 기다리지 않습니다. telnet 은 대개 설치돼 있지 않습니다.

2.8 IP·경로·DNS

bash
ip addr | grep 'inet '              # 내 IP
ip route | head -n 1                # 기본 게이트웨이
ping -c 3 10.0.0.5                  # ICMP, 막는 망이 많아 실패해도 단정 못 함
traceroute -n 10.0.0.5              # 어느 홉에서 끊기나
getent hosts db-prod                # /etc/hosts 와 DNS 순서로 풀기
dig +short db-prod                  # DNS 만
cat /etc/resolv.conf                # 어느 DNS 서버를 쓰나

getent 는 자바가 쓰는 것과 같은 순서로 이름을 풉니다. dig 는 되는데 getent 가 안 되면 /etc/hosts 나 nsswitch.conf 문제입니다.

2.9 firewalld 기본

RHEL 의 방화벽은 firewalld 이고 firewall-cmd 로 다룹니다. 영구 설정과 즉시 설정이 분리돼 있어 둘 다 해야 합니다.

bash
sudo firewall-cmd --state                                    # running
sudo firewall-cmd --zone=public --list-all                   # 열린 포트·서비스
sudo firewall-cmd --zone=public --add-port=8080/tcp --permanent
sudo firewall-cmd --reload                                   # permanent 적용
sudo firewall-cmd --zone=public --query-port=8080/tcp        # yes

--permanent 없이 열면 재부팅 뒤 닫히고, --permanent 만 하고 --reload 를 안 하면 지금은 안 열립니다. 이 레슨의 firewall.sh 가 세 줄을 묶습니다.

2.10 폐쇄망 프록시

외부로 나가는 요청은 프록시를 거칩니다. 셸 도구는 환경 변수, 자바는 시스템 속성으로 설정합니다.

bash
export http_proxy=http://proxy.corp:3128
export https_proxy=http://proxy.corp:3128
export no_proxy=localhost,127.0.0.1,.corp,10.0.0.0/8
bash
java -Dhttp.proxyHost=proxy.corp -Dhttp.proxyPort=3128 \
     -Dhttps.proxyHost=proxy.corp -Dhttps.proxyPort=3128 \
     -Dhttp.nonProxyHosts='localhost|127.0.0.1|*.corp' -jar app.jar

no_proxy 에 사내 도메인을 넣지 않으면 사내 DB 호출까지 프록시로 가서 실패합니다. 자바는 환경 변수를 안 읽으므로 -D 옵션이 따로 필요합니다.

2.11 사내 CA 인증서

폐쇄망 프록시나 사내 서버는 자체 서명 인증서를 씁니다. curl 은 시스템 저장소, 자바는 cacerts 에 CA 를 넣어야 TLS 오류가 사라집니다.

bash
sudo cp corp-ca.crt /etc/pki/ca-trust/source/anchors/ && sudo update-ca-trust
keytool -importcert -alias corp-ca -file corp-ca.crt -cacerts -storepass changeit -noprompt
curl -v https://api.corp/ 2>&1 | grep -i 'SSL certificate verify'

curl -k 는 검증을 끄는 것이라 진단에만 쓰고 스크립트에는 넣지 않습니다. 실무 확장 11 레슨의 CA 설정과 같은 내용입니다.

2.12 tcpdump 최소 사용

위 방법으로 안 잡히면 패킷을 봅니다. 개수 제한을 반드시 둡니다.

bash
sudo tcpdump -i any port 8080 -c 20 -nn
sudo tcpdump -i any host 10.0.0.5 and port 1521 -c 10 -w /tmp/db.pcap

SYN 만 나가고 SYN-ACK 이 없으면 중간에서 DROP 된 것입니다. -w 로 저장한 파일은 Wireshark 로 엽니다.

핵심 원리
  • 2.1 다섯 단계 진단 순서
  • 2.2 ss 로 포트 보기
  • 2.3 curl 기본 옵션
  • 2.4 curl 종료 코드
  • 2.5 응답 시간 분해
  • 2.6 POST 와 헤더
  • 2.7 포트 열림 확인: nc 와 /dev/tcp
  • 2.8 IP·경로·DNS
  • 2.9 firewalld 기본
  • 2.10 폐쇄망 프록시
  • 2.11 사내 CA 인증서
  • 2.12 tcpdump 최소 사용
이전 섹션1 왜 배우는가2 / 7다음 섹션3 코드 예제