ss 명령어: 리눅스 포트와 프로세스 확인, netstat 비교

리눅스 서버에서 어떤 포트가 열려 있고 누가 접속해 있는지는 ss 명령어로 확인합니다. ss는 netstat을 대신하는 iproute2의 소켓 조회 도구입니다. Debian 12 서버에서 ss로 수신 대기(LISTEN) 중인 포트와 접속을 조회한 결과, 일반 계정에서는 -p를 붙여도 다른 계정이 띄운 프로그램의 이름이 Process 칸에 나오지 않는 것을 확인했습니다.
아래 출력은 영어 locale로 실행한 결과입니다. 서버와 상대의 주소는 예시 주소로 표기했습니다.
1️⃣ ss 명령어 기본 사용법과 출력 칸
옵션 없이 ss를 실행하면 수신 대기 중인 포트는 빠지고 접속이 맺어진 소켓만 나옵니다. 테스트 서버에서는 맨 앞 줄들이 모두 서버 안 프로그램끼리 사용하는 유닉스 소켓(u_str, u_dgr)이었습니다.
ss | head -n 5Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
u_str ESTAB 0 0 * 1013903 * 1013904
u_dgr ESTAB 0 0 * 1013960 * 13394
u_str ESTAB 0 0 * 1013907 * 1013908
u_str ESTAB 0 0 * 46066198 * 46066199그래서 TCP 접속만 보려면 -t를 붙입니다. 유닉스 소켓이 빠지고, 포트 자리에는 번호 대신 ssh와 https 같은 서비스 이름이 뜹니다.
ss -tState Recv-Q Send-Q Local Address:Port Peer Address:Port Process
ESTAB 0 0 203.0.113.10:ssh 198.51.100.7:51114
ESTAB 0 0 203.0.113.10:26676 192.0.2.15:https
ESTAB 0 0 203.0.113.10:29714 192.0.2.16:https-n을 함께 붙이면 서비스 이름으로 바꾸지 않고 포트 번호가 그대로 나옵니다.
ss -tnState Recv-Q Send-Q Local Address:Port Peer Address:Port Process
ESTAB 0 0 203.0.113.10:22 198.51.100.7:51114
ESTAB 0 0 203.0.113.10:26676 192.0.2.15:443
ESTAB 0 0 203.0.113.10:29714 192.0.2.16:443Recv-Q와 Send-Q는 같은 칸이라도 소켓 상태에 따라 의미하는 값이 다릅니다. 접속 중인 소켓에서 Recv-Q는 받았지만 프로그램이 아직 읽지 않은 바이트 수이고, Send-Q는 보냈지만 상대가 아직 받았다고 확인하지 않은 바이트 수입니다.
수신 대기 소켓에서는 Recv-Q가 대기열에 쌓인 접속 수, Send-Q가 대기열 최대 크기를 의미합니다. 두 칸의 뜻은 net-tools의 netstat(8) man 페이지 설명입니다.
2️⃣ 리눅스 포트 확인(-tln, -uln, -tulpn)
옵션 없는 출력에는 접속을 기다리는 포트가 나오지 않으므로, 열린 포트를 확인할 때는 수신 대기 소켓만 고르는 -l을 붙입니다. [ss -tln]은 수신 대기 중인 TCP 포트를 번호로 출력합니다.
ss -tlnState Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 511 0.0.0.0:80 0.0.0.0:*
LISTEN 0 511 0.0.0.0:443 0.0.0.0:*
LISTEN 0 511 127.0.0.1:8080 0.0.0.0:*
LISTEN 0 128 [::]:22 [::]:*
LISTEN 0 511 [::]:80 [::]:*
LISTEN 0 511 [::]:443 [::]:*Local Address가 0.0.0.0이면 서버의 모든 IPv4 주소로 들어오는 접속을 받고, 127.0.0.1이면 서버 안에서만 접속할 수 있습니다. [::]는 IPv6의 모든 주소를 의미하므로, 22번과 80번, 443번 포트는 IPv4와 IPv6 양쪽에서 열려 있습니다.
-n을 빼면 포트 번호가 서비스 이름으로 바뀝니다. 8080번은 http-alt로 나옵니다.
ss -tlState Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
LISTEN 0 128 0.0.0.0:ssh 0.0.0.0:*
LISTEN 0 511 0.0.0.0:http 0.0.0.0:*
LISTEN 0 511 0.0.0.0:https 0.0.0.0:*
LISTEN 0 511 127.0.0.1:http-alt 0.0.0.0:*
LISTEN 0 128 [::]:ssh [::]:*
LISTEN 0 511 [::]:http [::]:*
LISTEN 0 511 [::]:https [::]:*UDP는 접속을 맺지 않는 방식이라 수신 대기 소켓에도 LISTEN 상태가 없습니다. [ss -uln] 출력의 상태 칸은 모두 UNCONN이었습니다. 68번(bootpc)은 DHCP 클라이언트, 123번(ntp)은 시간 동기화 포트입니다.
ss -ulnState Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
UNCONN 0 0 0.0.0.0:68 0.0.0.0:*
UNCONN 0 0 203.0.113.10:123 0.0.0.0:*
UNCONN 0 0 127.0.0.1:123 0.0.0.0:*
UNCONN 0 0 0.0.0.0:123 0.0.0.0:*
UNCONN 0 0 [::1]:123 [::]:*
UNCONN 0 0 [::]:123 [::]:*TCP와 UDP를 한 번에 보려면 [ss -tulpn]처럼 옵션을 모아 붙입니다. 종류가 둘 이상이면 맨 앞에 Netid 칸이 붙습니다.
ss -tulpnNetid State Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
udp UNCONN 0 0 0.0.0.0:68 0.0.0.0:*
udp UNCONN 0 0 203.0.113.10:123 0.0.0.0:*
udp UNCONN 0 0 127.0.0.1:123 0.0.0.0:*
udp UNCONN 0 0 0.0.0.0:123 0.0.0.0:*
udp UNCONN 0 0 [::1]:123 [::]:*
udp UNCONN 0 0 [::]:123 [::]:*
tcp LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
tcp LISTEN 0 511 0.0.0.0:80 0.0.0.0:*
tcp LISTEN 0 511 0.0.0.0:443 0.0.0.0:*
tcp LISTEN 0 511 127.0.0.1:8080 0.0.0.0:*
tcp LISTEN 0 128 [::]:22 [::]:*
tcp LISTEN 0 511 [::]:80 [::]:*
tcp LISTEN 0 511 [::]:443 [::]:*3️⃣ ss 명령어 프로세스 확인(-p)
-p는 소켓을 사용하는 프로그램을 Process 칸에 출력하는 옵션입니다. 그런데 테스트 서버의 일반 계정에서 [ss -tlnp]를 실행해 보니 아래처럼 Process 칸이 비어, 옵션이 적용되지 않은 것처럼 보였습니다.
ss -tlnpState Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 511 0.0.0.0:80 0.0.0.0:*
LISTEN 0 511 0.0.0.0:443 0.0.0.0:*
LISTEN 0 511 127.0.0.1:8080 0.0.0.0:*
LISTEN 0 128 [::]:22 [::]:*
LISTEN 0 511 [::]:80 [::]:*
LISTEN 0 511 [::]:443 [::]:*ss는 프로세스마다 /proc 아래 fd 폴더를 읽어 소켓을 사용하는 프로세스를 찾습니다. 다른 계정이 띄운 프로세스의 fd 폴더는 일반 계정이 열 수 없으므로, 그 프로그램의 이름은 칸에 들어가지 않습니다. root가 띄운 1번 프로세스의 폴더를 일반 계정에서 열면 권한 오류가 납니다.
ls /proc/1/fdls: cannot open directory '/proc/1/fd': Permission denied내 계정으로 띄운 프로그램은 일반 계정에서도 Process 칸에 나옵니다. python3의 간이 웹 서버를 127.0.0.1의 8000번 포트로 띄워 확인했습니다.
python3 -m http.server 8000 --bind 127.0.0.1 &띄운 뒤에는 [sport = :8000]을 붙여 8000번 포트의 줄만 조회합니다.
ss -tlnp sport = :8000State Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
LISTEN 0 5 127.0.0.1:8000 0.0.0.0:* users:(("python3",pid=343015,fd=3))users 뒤 괄호에는 프로그램 이름과 pid, 파일 디스크립터 번호(fd)가 차례로 들어갑니다.
확인을 마친 간이 웹 서버는 [kill %1]로 끕니다. 끈 뒤에 [ss -tln sport = :8000]을 다시 실행하면 머리줄만 남고 8000번 줄은 나오지 않습니다.
root 계정에서 실행하면 모든 프로세스의 정보를 읽을 수 있어 Process 칸이 채워집니다. 한 포트에서 여러 프로세스가 함께 수신 대기 중이면 그 수만큼 users 괄호 안 항목이 이어집니다. 아래 root 출력의 프로그램 이름과 pid는 예시 값입니다.
ss -tlnp sport = :443State Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
LISTEN 0 511 0.0.0.0:443 0.0.0.0:* users:(("app",pid=2101,fd=6),("app",pid=2100,fd=6))
LISTEN 0 511 [::]:443 [::]:* users:(("app",pid=2101,fd=7),("app",pid=2100,fd=7))포트 번호로 프로그램을 찾을 때는 lsof 명령어의 [lsof -i :443] 꼴도 사용할 수 있습니다.
계정에 따라 Process 칸이 어떻게 달라지는지는 아래 다이어그램에서 계정을 바꿔 가며 비교할 수 있습니다.
4️⃣ ss 상태와 포트 필터 옵션
열린 포트를 확인한 뒤에도 지금 그 포트로 누가 접속해 있는지는 따로 골라야 합니다. ss는 옵션 뒤에 필터 조건을 붙여 원하는 줄만 남깁니다.
state 뒤에 상태 이름을 적으면 그 상태의 소켓만 남습니다. [ss -tn state established]의 출력은 State 칸 없이 Recv-Q 칸부터 시작합니다.
ss -tn state establishedRecv-Q Send-Q Local Address:Port Peer Address:Port Process
0 0 203.0.113.10:22 198.51.100.7:51114
0 0 203.0.113.10:26676 192.0.2.15:443
0 0 203.0.113.10:29714 192.0.2.16:443포트는 dport(상대 쪽 포트)와 sport(내 쪽 포트)로 거릅니다. 서버에서 바깥 https 서버로 나간 접속은 [dport = :443]으로 고릅니다.
ss -tn dport = :443State Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
ESTAB 0 0 203.0.113.10:26676 192.0.2.15:443
ESTAB 0 0 203.0.113.10:29714 192.0.2.16:443sport를 -l과 함께 사용하면 그 포트가 수신 대기 중인지만 확인할 수 있습니다.
ss -tln sport = :22State Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 128 [::]:22 [::]:*조건 여러 개는 괄호와 or로 묶고, 셸이 괄호를 먼저 읽지 않게 작은따옴표로 감쌉니다. 아래는 man 페이지 예시를 따라 ssh 접속만 고른 결과입니다.
ss -tn state established '( dport = :ssh or sport = :ssh )'Recv-Q Send-Q Local Address:Port Peer Address:Port Process
0 0 203.0.113.10:22 198.51.100.7:51114TIME-WAIT는 접속이 끊긴 뒤 잠시 남아 있는 상태입니다. 기본 출력에는 나오지 않으므로 [state time-wait]로 따로 골라야 보입니다.
ss -tn state time-waitRecv-Q Send-Q Local Address:Port Peer Address:PortProcess
0 0 127.0.0.1:28750 127.0.0.1:80
0 0 127.0.0.1:57698 127.0.0.1:8080
0 0 [::1]:31936 [::1]:80상태 이름을 잘못 적으면 [wrong state name] 오류 한 줄만 남기고 명령이 바로 끝납니다. 아래는 일부러 foo를 넣은 결과입니다. 사용할 수 있는 이름은 [ss -h] 출력의 TCP-STATES 줄에서 확인할 수 있습니다.
ss -tn state fooss: wrong state name: foo📌 주요 옵션: 이 글에서 실행한 결과
| 옵션 | 하는 일 | 이 글에서 본 결과 | |
|---|---|---|---|
| -t | TCP 소켓만 출력 | 유닉스 소켓이 빠지고, 포트 자리에 ssh와 https 같은 서비스 이름이 나옴 | |
| -n | 서비스 이름으로 바꾸지 않고 포트 번호로 출력 | ss -tn에서 ssh가 22, https가 443으로 나옴 | |
| -l | 수신 대기(LISTEN) 소켓만 출력 | ss -tln에 22번, 80번, 443번 같은 수신 대기 포트가 나옴 | |
| -u | UDP 소켓만 출력 | ss -uln의 상태 칸이 모두 UNCONN | |
| -p | 소켓을 사용하는 프로그램을 Process 칸에 출력 | 일반 계정에서는 내 계정이 띄운 python3만 이름과 pid가 나오고, 다른 계정의 프로그램은 빈칸 | |
| -s | 소켓 목록 대신 종류별 개수를 요약 | TCP 줄의 estab 9가 state established 출력에서 머리줄을 뺀 9줄과 같음 | |
| -4 | IPv4 소켓만 출력 | ss -t4ln에서 [::]로 시작하는 줄이 빠짐 | |
| -6 | IPv6 소켓만 출력 | ss -t6ln에서 0.0.0.0과 127.0.0.1로 시작하는 줄이 빠짐 | |
| -H | 머리줄 없이 소켓 줄만 출력 | ss -H -tln | wc -l의 줄 수에 머리줄이 세어지지 않음 | |
| state 상태 | 그 상태의 소켓만 남김 | state established 출력은 State 칸 없이 Recv-Q부터 시작, 없는 이름은 [wrong state name: foo] | |
| dport = :포트 | 상대 쪽 포트로 거름 | dport = :443에 바깥 https 서버로 나간 접속 두 줄 | |
| sport = :포트 | 내 쪽 포트로 거름 | -l과 함께 쓴 sport = :22에 IPv4와 IPv6의 22번 수신 대기 두 줄 | |
| src 주소 | 그 주소의 소켓만 남김 | ss -tln src 127.0.0.1에 서버 안에서만 접속을 받는 127.0.0.1 쪽 포트만 나옴 |
📎 그 밖의 옵션: 공식 매뉴얼 기준
| 옵션 | 하는 일 | |
|---|---|---|
| -a, --all | 수신 대기 소켓과 접속 중인 소켓을 함께 출력 | |
| -r, --resolve | 주소와 포트 번호를 이름으로 풀어 출력 | |
| -e, --extended | 소켓마다 uid, inode 같은 자세한 정보를 출력 | |
| -o, --options | TCP 재전송, keepalive 같은 타이머 정보를 출력 | |
| -m, --memory | 소켓이 사용하는 메모리를 출력 | |
| -i, --info | TCP 내부 정보(rtt, cwnd 등)를 출력 | |
| -x, --unix | 유닉스 도메인 소켓만 출력 | |
| -w, --raw | RAW 소켓만 출력 | |
| -f 종류 | unix, inet, inet6, link, netlink 같은 소켓 종류로 고름 | |
| -Q, --no-queues | Recv-Q와 Send-Q 칸을 빼고 출력 | |
| -K, --kill | 필터에 맞는 소켓을 강제로 닫음, 커널이 지원하지 않는 소켓은 건너뜀 | |
| -E, --events | 닫히는 소켓을 계속 출력 | |
| -V, --version | 버전 정보를 출력 |
🔲 ss 명령어 시뮬레이터
아래 시뮬레이터에서 지금까지 나온 옵션과 필터를 직접 입력하고, [netstat -tln]과 출력을 비교할 수 있습니다.
5️⃣ ss 소켓 요약(-s)
-s는 소켓 목록 대신 종류별 개수를 요약해 출력합니다. man 페이지에 따르면 목록을 하나씩 세지 않고 여러 통계 자료에서 숫자를 모읍니다.
ss -sTotal: 340
TCP: 48 (estab 9, closed 15, orphaned 0, timewait 13)
Transport Total IP IPv6
RAW 0 0 0
UDP 8 4 4
TCP 33 25 8
INET 41 29 12
FRAG 0 0 0TCP 줄의 estab는 지금 맺어진 접속 수입니다. 그래서 같은 시점에 [state established]로 출력한 줄 수와 맞춰 볼 수 있습니다.
ss -tn state established | wc -l10출력 10줄에서 머리줄 하나를 빼면 9줄로, -s의 estab 9와 같았습니다. timewait 13은 [state time-wait]로 골라야 보이던 TIME-WAIT 소켓 수입니다.
6️⃣ ss 명령어와 netstat 비교
netstat이 들어 있는 net-tools 패키지의 man 페이지는 netstat을 거의 쓰이지 않게 된 프로그램(mostly obsolete)으로 적고, 대신 ss를 사용하도록 안내합니다. 다만 netstat 출력 꼴에 맞춰 짠 스크립트는 ss로 바꾸면 칸 순서와 주소 표기가 달라 그대로 읽지 못합니다.
같은 서버에서 수신 대기 중인 TCP 포트를 두 명령으로 출력해 보니, netstat은 상태가 맨 끝에 오고 IPv6 주소를 :::22처럼 적었습니다.
netstat -tlnActive Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:8080 0.0.0.0:* LISTEN
tcp6 0 0 :::22 :::* LISTEN
tcp6 0 0 :::80 :::* LISTEN
tcp6 0 0 :::443 :::* LISTENss에서는 상태가 맨 앞에 오고, IPv6 주소를 [::]:22처럼 대괄호로 감쌉니다.
ss -tlnState Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 511 0.0.0.0:80 0.0.0.0:*
LISTEN 0 511 0.0.0.0:443 0.0.0.0:*
LISTEN 0 511 127.0.0.1:8080 0.0.0.0:*
LISTEN 0 128 [::]:22 [::]:*
LISTEN 0 511 [::]:80 [::]:*
LISTEN 0 511 [::]:443 [::]:*자주 사용하는 netstat 옵션을 ss와 ip 명령으로 옮기면 아래와 같습니다.
| netstat | 대신할 명령 / 보는 것 |
|---|---|
| netstat -tln | ss -tln수신 대기 중인 TCP 포트를 번호로 |
| netstat -tulpn | ss -tulpn수신 대기 중인 TCP·UDP 포트와 프로그램 |
| netstat -tan | ss -tan모든 TCP 소켓을 번호로 |
| netstat -r | ip route라우팅 표 |
| netstat -i | ip -s link네트워크 인터페이스 통계 |
🔢 FAQ & 추천 콘텐츠









ℹ️ 제휴 안내
본 사이트의 콘텐츠에는 제휴 링크가 포함되어 있습니다. 방문자가 이 링크를 통해 상품 또는 서비스를 구매하면 본 사이트는 판매처로부터 수수료를 지급받습니다. 이 과정에서 구매자가 지불하는 금액(이벤트 할인 시 금액이 내려갑니다↓)은 오르지 않습니다. 게시된 가격·할인·재고 정보는 작성 시점 기준이며 실제와 다를 수 있으므로, 구매 전 판매처에서 최종 확인하시기 바랍니다. 상품 선정과 평가는 자체 기준에 따라 작성되며, 수수료 지급 여부가 소개 순서나 평가 내용에 영향을 주지 않습니다.
