[{"data":1,"prerenderedAt":1579},["ShallowReactive",2],{"page-en-\u002Fblog\u002Flinux-network-troubleshooting":3,"related-en-\u002Fblog\u002Flinux-network-troubleshooting":1555},{"id":4,"title":5,"body":6,"date":1541,"description":1542,"extension":1543,"meta":1544,"navigation":1207,"path":1545,"seo":1546,"stem":1547,"tags":1548,"translation":1553,"__hash__":1554},"pages_en\u002Fen\u002Fblog\u002Flinux-network-troubleshooting.md","Linux Networking and Troubleshooting Commands: curl, ss, dig, tcpdump",{"type":7,"value":8,"toc":1528},"minimark",[9,14,23,26,30,141,165,169,247,256,260,399,415,421,425,608,611,637,643,647,747,813,837,841,946,949,993,997,1000,1144,1158,1162,1275,1282,1286,1292,1425,1501,1505,1524],[10,11,13],"h2",{"id":12},"introduction","Introduction",[15,16,17,18,22],"p",{},"Behind a \"the service is unreachable\" complaint there can be dozens of causes: DNS resolves wrong, nothing listens on the port, a firewall blocks it, the certificate is invalid, or the app only listens on ",[19,20,21],"code",{},"localhost",". With the right commands you can tell which one in a few minutes.",[15,24,25],{},"This post lists the commands used to narrow the problem down layer by layer: interface → DNS → connectivity → port → application → packets.",[10,27,29],{"id":28},"_1-interfaces-ips-and-routes","1. Interfaces, IPs and routes",[31,32,37],"pre",{"className":33,"code":34,"language":35,"meta":36,"style":36},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","ip a                         # interfaces and IP addresses (ip addr)\nip -br a                     # brief summary\nip r                         # routing table; \"default via\" → gateway\nip r get 8.8.8.8             # which interface\u002Fgateway reaches this target\nip link set eth0 up\nhostname -I                  # the server's IPs\ncurl -s ifconfig.me          # public IP as seen from outside\n","bash","",[19,38,39,56,69,80,97,114,126],{"__ignoreMap":36},[40,41,44,48,52],"span",{"class":42,"line":43},"line",1,[40,45,47],{"class":46},"sBMFI","ip",[40,49,51],{"class":50},"sfazB"," a",[40,53,55],{"class":54},"sHwdD","                         # interfaces and IP addresses (ip addr)\n",[40,57,59,61,64,66],{"class":42,"line":58},2,[40,60,47],{"class":46},[40,62,63],{"class":50}," -br",[40,65,51],{"class":50},[40,67,68],{"class":54},"                     # brief summary\n",[40,70,72,74,77],{"class":42,"line":71},3,[40,73,47],{"class":46},[40,75,76],{"class":50}," r",[40,78,79],{"class":54},"                         # routing table; \"default via\" → gateway\n",[40,81,83,85,87,90,94],{"class":42,"line":82},4,[40,84,47],{"class":46},[40,86,76],{"class":50},[40,88,89],{"class":50}," get",[40,91,93],{"class":92},"sbssI"," 8.8.8.8",[40,95,96],{"class":54},"             # which interface\u002Fgateway reaches this target\n",[40,98,100,102,105,108,111],{"class":42,"line":99},5,[40,101,47],{"class":46},[40,103,104],{"class":50}," link",[40,106,107],{"class":50}," set",[40,109,110],{"class":50}," eth0",[40,112,113],{"class":50}," up\n",[40,115,117,120,123],{"class":42,"line":116},6,[40,118,119],{"class":46},"hostname",[40,121,122],{"class":50}," -I",[40,124,125],{"class":54},"                  # the server's IPs\n",[40,127,129,132,135,138],{"class":42,"line":128},7,[40,130,131],{"class":46},"curl",[40,133,134],{"class":50}," -s",[40,136,137],{"class":50}," ifconfig.me",[40,139,140],{"class":54},"          # public IP as seen from outside\n",[15,142,143,146,147,150,151,154,155,158,159,150,161,164],{},[19,144,145],{},"ifconfig",", ",[19,148,149],{},"netstat"," and ",[19,152,153],{},"route"," come from the ",[19,156,157],{},"net-tools"," package, which most distributions no longer install by default; ",[19,160,47],{},[19,162,163],{},"ss"," replaced them.",[10,166,168],{"id":167},"_2-reachability-ping-traceroute-mtr","2. Reachability: ping, traceroute, mtr",[31,170,172],{"className":33,"code":171,"language":35,"meta":36,"style":36},"ping -c 4 example.com        # send 4 packets\nping -c 4 -W 2 10.0.1.15     # 2 s timeout\ntraceroute example.com       # routers along the path\ntracepath example.com        # alternative that needs no root\nmtr -rwc 50 example.com      # ping + traceroute, loss\u002Flatency report per hop\n",[19,173,174,191,211,221,231],{"__ignoreMap":36},[40,175,176,179,182,185,188],{"class":42,"line":43},[40,177,178],{"class":46},"ping",[40,180,181],{"class":50}," -c",[40,183,184],{"class":92}," 4",[40,186,187],{"class":50}," example.com",[40,189,190],{"class":54},"        # send 4 packets\n",[40,192,193,195,197,199,202,205,208],{"class":42,"line":58},[40,194,178],{"class":46},[40,196,181],{"class":50},[40,198,184],{"class":92},[40,200,201],{"class":50}," -W",[40,203,204],{"class":92}," 2",[40,206,207],{"class":92}," 10.0.1.15",[40,209,210],{"class":54},"     # 2 s timeout\n",[40,212,213,216,218],{"class":42,"line":71},[40,214,215],{"class":46},"traceroute",[40,217,187],{"class":50},[40,219,220],{"class":54},"       # routers along the path\n",[40,222,223,226,228],{"class":42,"line":82},[40,224,225],{"class":46},"tracepath",[40,227,187],{"class":50},[40,229,230],{"class":54},"        # alternative that needs no root\n",[40,232,233,236,239,242,244],{"class":42,"line":99},[40,234,235],{"class":46},"mtr",[40,237,238],{"class":50}," -rwc",[40,240,241],{"class":92}," 50",[40,243,187],{"class":50},[40,245,246],{"class":54},"      # ping + traceroute, loss\u002Flatency report per hop\n",[248,249,250],"blockquote",{},[15,251,252,253,255],{},"No ",[19,254,178],{}," reply doesn't mean the server is down. Many cloud providers and firewalls block ICMP; test the TCP port directly in the next step.",[10,257,259],{"id":258},"_3-dns-dig-nslookup-getent","3. DNS: dig, nslookup, getent",[31,261,263],{"className":33,"code":262,"language":35,"meta":36,"style":36},"dig example.com              # A record, TTL, answering server\ndig +short example.com\ndig example.com AAAA         # IPv6\ndig example.com MX\ndig example.com TXT          # SPF, verification records\ndig @8.8.8.8 example.com     # ask a specific DNS server\ndig +trace example.com       # resolution chain from the root\ndig -x 203.0.113.10          # reverse (PTR) lookup\nnslookup example.com\ngetent hosts example.com     # what the system actually uses (including \u002Fetc\u002Fhosts)\nresolvectl status            # DNS servers on systems using systemd-resolved\ncat \u002Fetc\u002Fresolv.conf\n",[19,264,265,275,285,297,306,318,330,342,356,364,378,390],{"__ignoreMap":36},[40,266,267,270,272],{"class":42,"line":43},[40,268,269],{"class":46},"dig",[40,271,187],{"class":50},[40,273,274],{"class":54},"              # A record, TTL, answering server\n",[40,276,277,279,282],{"class":42,"line":58},[40,278,269],{"class":46},[40,280,281],{"class":50}," +short",[40,283,284],{"class":50}," example.com\n",[40,286,287,289,291,294],{"class":42,"line":71},[40,288,269],{"class":46},[40,290,187],{"class":50},[40,292,293],{"class":50}," AAAA",[40,295,296],{"class":54},"         # IPv6\n",[40,298,299,301,303],{"class":42,"line":82},[40,300,269],{"class":46},[40,302,187],{"class":50},[40,304,305],{"class":50}," MX\n",[40,307,308,310,312,315],{"class":42,"line":99},[40,309,269],{"class":46},[40,311,187],{"class":50},[40,313,314],{"class":50}," TXT",[40,316,317],{"class":54},"          # SPF, verification records\n",[40,319,320,322,325,327],{"class":42,"line":116},[40,321,269],{"class":46},[40,323,324],{"class":50}," @8.8.8.8",[40,326,187],{"class":50},[40,328,329],{"class":54},"     # ask a specific DNS server\n",[40,331,332,334,337,339],{"class":42,"line":128},[40,333,269],{"class":46},[40,335,336],{"class":50}," +trace",[40,338,187],{"class":50},[40,340,341],{"class":54},"       # resolution chain from the root\n",[40,343,345,347,350,353],{"class":42,"line":344},8,[40,346,269],{"class":46},[40,348,349],{"class":50}," -x",[40,351,352],{"class":92}," 203.0.113.10",[40,354,355],{"class":54},"          # reverse (PTR) lookup\n",[40,357,359,362],{"class":42,"line":358},9,[40,360,361],{"class":46},"nslookup",[40,363,284],{"class":50},[40,365,367,370,373,375],{"class":42,"line":366},10,[40,368,369],{"class":46},"getent",[40,371,372],{"class":50}," hosts",[40,374,187],{"class":50},[40,376,377],{"class":54},"     # what the system actually uses (including \u002Fetc\u002Fhosts)\n",[40,379,381,384,387],{"class":42,"line":380},11,[40,382,383],{"class":46},"resolvectl",[40,385,386],{"class":50}," status",[40,388,389],{"class":54},"            # DNS servers on systems using systemd-resolved\n",[40,391,393,396],{"class":42,"line":392},12,[40,394,395],{"class":46},"cat",[40,397,398],{"class":50}," \u002Fetc\u002Fresolv.conf\n",[15,400,401,403,404,407,408,411,412,414],{},[19,402,269],{}," asks DNS directly; ",[19,405,406],{},"getent hosts"," returns what applications see, ",[19,409,410],{},"\u002Fetc\u002Fhosts"," included. If they differ, the problem is usually ",[19,413,410],{}," or a local cache.",[15,416,417,418,420],{},"If you just changed a DNS record, the old value can stay in caches until its TTL expires; the TTL in ",[19,419,269],{}," output shows the time remaining.",[10,422,424],{"id":423},"_4-http-curl","4. HTTP: curl",[31,426,428],{"className":33,"code":427,"language":35,"meta":36,"style":36},"curl https:\u002F\u002Fapi.example.com\u002Fhealth\ncurl -I https:\u002F\u002Fexample.com                 # headers only\ncurl -v https:\u002F\u002Fexample.com                 # DNS, TCP, TLS handshake, headers\ncurl -L http:\u002F\u002Fexample.com                  # follow redirects\ncurl -sS -o \u002Fdev\u002Fnull -w \"%{http_code}\\n\" https:\u002F\u002Fexample.com\ncurl -X POST https:\u002F\u002Fapi.example.com\u002Fusers \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"name\":\"Sukru\"}'\ncurl -H \"Authorization: Bearer $TOKEN\" https:\u002F\u002Fapi.example.com\u002Fme\ncurl --max-time 5 https:\u002F\u002Fexample.com\ncurl -k https:\u002F\u002Fself-signed.local           # skip certificate verification (testing only)\ncurl --resolve example.com:443:203.0.113.10 https:\u002F\u002Fexample.com   # bypass DNS, hit a specific IP\n",[19,429,430,437,449,461,474,503,520,534,548,568,580,593],{"__ignoreMap":36},[40,431,432,434],{"class":42,"line":43},[40,433,131],{"class":46},[40,435,436],{"class":50}," https:\u002F\u002Fapi.example.com\u002Fhealth\n",[40,438,439,441,443,446],{"class":42,"line":58},[40,440,131],{"class":46},[40,442,122],{"class":50},[40,444,445],{"class":50}," https:\u002F\u002Fexample.com",[40,447,448],{"class":54},"                 # headers only\n",[40,450,451,453,456,458],{"class":42,"line":71},[40,452,131],{"class":46},[40,454,455],{"class":50}," -v",[40,457,445],{"class":50},[40,459,460],{"class":54},"                 # DNS, TCP, TLS handshake, headers\n",[40,462,463,465,468,471],{"class":42,"line":82},[40,464,131],{"class":46},[40,466,467],{"class":50}," -L",[40,469,470],{"class":50}," http:\u002F\u002Fexample.com",[40,472,473],{"class":54},"                  # follow redirects\n",[40,475,476,478,481,484,487,490,494,497,500],{"class":42,"line":99},[40,477,131],{"class":46},[40,479,480],{"class":50}," -sS",[40,482,483],{"class":50}," -o",[40,485,486],{"class":50}," \u002Fdev\u002Fnull",[40,488,489],{"class":50}," -w",[40,491,493],{"class":492},"sMK4o"," \"",[40,495,496],{"class":50},"%{http_code}\\n",[40,498,499],{"class":492},"\"",[40,501,502],{"class":50}," https:\u002F\u002Fexample.com\n",[40,504,505,507,510,513,516],{"class":42,"line":116},[40,506,131],{"class":46},[40,508,509],{"class":50}," -X",[40,511,512],{"class":50}," POST",[40,514,515],{"class":50}," https:\u002F\u002Fapi.example.com\u002Fusers",[40,517,519],{"class":518},"sTEyZ"," \\\n",[40,521,522,525,527,530,532],{"class":42,"line":128},[40,523,524],{"class":50},"  -H",[40,526,493],{"class":492},[40,528,529],{"class":50},"Content-Type: application\u002Fjson",[40,531,499],{"class":492},[40,533,519],{"class":518},[40,535,536,539,542,545],{"class":42,"line":344},[40,537,538],{"class":50},"  -d",[40,540,541],{"class":492}," '",[40,543,544],{"class":50},"{\"name\":\"Sukru\"}",[40,546,547],{"class":492},"'\n",[40,549,550,552,555,557,560,563,565],{"class":42,"line":358},[40,551,131],{"class":46},[40,553,554],{"class":50}," -H",[40,556,493],{"class":492},[40,558,559],{"class":50},"Authorization: Bearer ",[40,561,562],{"class":518},"$TOKEN",[40,564,499],{"class":492},[40,566,567],{"class":50}," https:\u002F\u002Fapi.example.com\u002Fme\n",[40,569,570,572,575,578],{"class":42,"line":366},[40,571,131],{"class":46},[40,573,574],{"class":50}," --max-time",[40,576,577],{"class":92}," 5",[40,579,502],{"class":50},[40,581,582,584,587,590],{"class":42,"line":380},[40,583,131],{"class":46},[40,585,586],{"class":50}," -k",[40,588,589],{"class":50}," https:\u002F\u002Fself-signed.local",[40,591,592],{"class":54},"           # skip certificate verification (testing only)\n",[40,594,595,597,600,603,605],{"class":42,"line":392},[40,596,131],{"class":46},[40,598,599],{"class":50}," --resolve",[40,601,602],{"class":50}," example.com:443:203.0.113.10",[40,604,445],{"class":50},[40,606,607],{"class":54},"   # bypass DNS, hit a specific IP\n",[15,609,610],{},"Timing output to see where a response slows down:",[31,612,614],{"className":33,"code":613,"language":35,"meta":36,"style":36},"curl -sS -o \u002Fdev\u002Fnull -w \"dns:%{time_namelookup} connect:%{time_connect} tls:%{time_appconnect} ttfb:%{time_starttransfer} total:%{time_total}\\n\" https:\u002F\u002Fexample.com\n",[19,615,616],{"__ignoreMap":36},[40,617,618,620,622,624,626,628,630,633,635],{"class":42,"line":43},[40,619,131],{"class":46},[40,621,480],{"class":50},[40,623,483],{"class":50},[40,625,486],{"class":50},[40,627,489],{"class":50},[40,629,493],{"class":492},[40,631,632],{"class":50},"dns:%{time_namelookup} connect:%{time_connect} tls:%{time_appconnect} ttfb:%{time_starttransfer} total:%{time_total}\\n",[40,634,499],{"class":492},[40,636,502],{"class":50},[15,638,639,642],{},[19,640,641],{},"--resolve"," is very handy for testing a new server before switching DNS, or for trying a single node behind a load balancer.",[10,644,646],{"id":645},"_5-ports-and-connections-ss-lsof","5. Ports and connections: ss, lsof",[31,648,650],{"className":33,"code":649,"language":35,"meta":36,"style":36},"ss -tlnp                     # listening TCP ports and processes\nss -ulnp                     # listening UDP ports\nss -tnp                      # established TCP connections\nss -tn state established '( dport = :5432 )'   # connections to PostgreSQL\nss -s                        # summary statistics\nsudo lsof -i :8080           # process using 8080\nsudo fuser -k 8080\u002Ftcp       # kill the process using 8080\n",[19,651,652,662,672,682,706,715,732],{"__ignoreMap":36},[40,653,654,656,659],{"class":42,"line":43},[40,655,163],{"class":46},[40,657,658],{"class":50}," -tlnp",[40,660,661],{"class":54},"                     # listening TCP ports and processes\n",[40,663,664,666,669],{"class":42,"line":58},[40,665,163],{"class":46},[40,667,668],{"class":50}," -ulnp",[40,670,671],{"class":54},"                     # listening UDP ports\n",[40,673,674,676,679],{"class":42,"line":71},[40,675,163],{"class":46},[40,677,678],{"class":50}," -tnp",[40,680,681],{"class":54},"                      # established TCP connections\n",[40,683,684,686,689,692,695,697,700,703],{"class":42,"line":82},[40,685,163],{"class":46},[40,687,688],{"class":50}," -tn",[40,690,691],{"class":50}," state",[40,693,694],{"class":50}," established",[40,696,541],{"class":492},[40,698,699],{"class":50},"( dport = :5432 )",[40,701,702],{"class":492},"'",[40,704,705],{"class":54},"   # connections to PostgreSQL\n",[40,707,708,710,712],{"class":42,"line":99},[40,709,163],{"class":46},[40,711,134],{"class":50},[40,713,714],{"class":54},"                        # summary statistics\n",[40,716,717,720,723,726,729],{"class":42,"line":116},[40,718,719],{"class":46},"sudo",[40,721,722],{"class":50}," lsof",[40,724,725],{"class":50}," -i",[40,727,728],{"class":50}," :8080",[40,730,731],{"class":54},"           # process using 8080\n",[40,733,734,736,739,741,744],{"class":42,"line":128},[40,735,719],{"class":46},[40,737,738],{"class":50}," fuser",[40,740,586],{"class":50},[40,742,743],{"class":50}," 8080\u002Ftcp",[40,745,746],{"class":54},"       # kill the process using 8080\n",[748,749,750,765],"table",{},[751,752,753],"thead",{},[754,755,756,762],"tr",{},[757,758,759,761],"th",{},[19,760,163],{}," flag",[757,763,764],{},"Meaning",[766,767,768,783,793,803],"tbody",{},[754,769,770,780],{},[771,772,773,776,777],"td",{},[19,774,775],{},"-t"," \u002F ",[19,778,779],{},"-u",[771,781,782],{},"TCP \u002F UDP",[754,784,785,790],{},[771,786,787],{},[19,788,789],{},"-l",[771,791,792],{},"Listening sockets only",[754,794,795,800],{},[771,796,797],{},[19,798,799],{},"-n",[771,801,802],{},"No name resolution (show port numbers)",[754,804,805,810],{},[771,806,807],{},[19,808,809],{},"-p",[771,811,812],{},"Show the process (sudo for other users' processes)",[15,814,815,816,820,821,824,825,828,829,832,833,836],{},"Watch the ",[817,818,819],"strong",{},"Local Address"," column in ",[19,822,823],{},"ss -tlnp",": ",[19,826,827],{},"127.0.0.1:8080"," is reachable only from the server itself, ",[19,830,831],{},"0.0.0.0:8080"," or ",[19,834,835],{},"*:8080"," from every interface. It's the most common cause of \"works locally, unreachable from outside\".",[10,838,840],{"id":839},"_6-testing-a-tcp-port-nc","6. Testing a TCP port: nc",[31,842,844],{"className":33,"code":843,"language":35,"meta":36,"style":36},"nc -zv db.example.com 5432           # is the port open?\nnc -zv 10.0.1.15 20-25               # a port range\ntimeout 3 bash -c '\u003C\u002Fdev\u002Ftcp\u002F10.0.1.15\u002F6379' && echo open || echo closed   # without nc\nopenssl s_client -connect example.com:443 -servername example.com \u003C\u002Fdev\u002Fnull   # TLS and certificate chain\n",[19,845,846,863,877,918],{"__ignoreMap":36},[40,847,848,851,854,857,860],{"class":42,"line":43},[40,849,850],{"class":46},"nc",[40,852,853],{"class":50}," -zv",[40,855,856],{"class":50}," db.example.com",[40,858,859],{"class":92}," 5432",[40,861,862],{"class":54},"           # is the port open?\n",[40,864,865,867,869,871,874],{"class":42,"line":58},[40,866,850],{"class":46},[40,868,853],{"class":50},[40,870,207],{"class":92},[40,872,873],{"class":50}," 20-25",[40,875,876],{"class":54},"               # a port range\n",[40,878,879,882,885,888,890,892,895,897,900,904,907,910,912,915],{"class":42,"line":71},[40,880,881],{"class":46},"timeout",[40,883,884],{"class":92}," 3",[40,886,887],{"class":50}," bash",[40,889,181],{"class":50},[40,891,541],{"class":492},[40,893,894],{"class":50},"\u003C\u002Fdev\u002Ftcp\u002F10.0.1.15\u002F6379",[40,896,702],{"class":492},[40,898,899],{"class":492}," &&",[40,901,903],{"class":902},"s2Zo4"," echo",[40,905,906],{"class":50}," open",[40,908,909],{"class":492}," ||",[40,911,903],{"class":902},[40,913,914],{"class":50}," closed",[40,916,917],{"class":54},"   # without nc\n",[40,919,920,923,926,929,932,935,937,940,943],{"class":42,"line":82},[40,921,922],{"class":46},"openssl",[40,924,925],{"class":50}," s_client",[40,927,928],{"class":50}," -connect",[40,930,931],{"class":50}," example.com:443",[40,933,934],{"class":50}," -servername",[40,936,187],{"class":50},[40,938,939],{"class":492}," \u003C",[40,941,942],{"class":50},"\u002Fdev\u002Fnull",[40,944,945],{"class":54},"   # TLS and certificate chain\n",[15,947,948],{},"Reading the results:",[748,950,951,960],{},[751,952,953],{},[754,954,955,958],{},[757,956,957],{},"Result",[757,959,764],{},[766,961,962,975,985],{},[754,963,964,972],{},[771,965,966,776,969],{},[19,967,968],{},"succeeded",[19,970,971],{},"open",[771,973,974],{},"The port is open and a process is listening",[754,976,977,982],{},[771,978,979],{},[19,980,981],{},"Connection refused",[771,983,984],{},"The host was reached but nothing listens on that port",[754,986,987,990],{},[771,988,989],{},"Timeout",[771,991,992],{},"A firewall in between silently drops packets, or the host is unreachable",[10,994,996],{"id":995},"_7-packet-capture-tcpdump","7. Packet capture: tcpdump",[15,998,999],{},"When everything else looks fine but the problem persists, look at what's actually on the wire:",[31,1001,1003],{"className":33,"code":1002,"language":35,"meta":36,"style":36},"sudo tcpdump -i any port 8080                     # traffic on 8080\nsudo tcpdump -i eth0 host 10.0.1.15               # a specific host\nsudo tcpdump -i any -nn 'tcp port 443 and host 203.0.113.10'\nsudo tcpdump -i any -nn port 53                   # DNS queries\nsudo tcpdump -i any -A -s 0 port 80               # print HTTP content as ASCII\nsudo tcpdump -i any -w capture.pcap port 5432     # write to a file for Wireshark\nsudo tcpdump -r capture.pcap\n",[19,1004,1005,1026,1044,1064,1084,1110,1132],{"__ignoreMap":36},[40,1006,1007,1009,1012,1014,1017,1020,1023],{"class":42,"line":43},[40,1008,719],{"class":46},[40,1010,1011],{"class":50}," tcpdump",[40,1013,725],{"class":50},[40,1015,1016],{"class":50}," any",[40,1018,1019],{"class":50}," port",[40,1021,1022],{"class":92}," 8080",[40,1024,1025],{"class":54},"                     # traffic on 8080\n",[40,1027,1028,1030,1032,1034,1036,1039,1041],{"class":42,"line":58},[40,1029,719],{"class":46},[40,1031,1011],{"class":50},[40,1033,725],{"class":50},[40,1035,110],{"class":50},[40,1037,1038],{"class":50}," host",[40,1040,207],{"class":92},[40,1042,1043],{"class":54},"               # a specific host\n",[40,1045,1046,1048,1050,1052,1054,1057,1059,1062],{"class":42,"line":71},[40,1047,719],{"class":46},[40,1049,1011],{"class":50},[40,1051,725],{"class":50},[40,1053,1016],{"class":50},[40,1055,1056],{"class":50}," -nn",[40,1058,541],{"class":492},[40,1060,1061],{"class":50},"tcp port 443 and host 203.0.113.10",[40,1063,547],{"class":492},[40,1065,1066,1068,1070,1072,1074,1076,1078,1081],{"class":42,"line":82},[40,1067,719],{"class":46},[40,1069,1011],{"class":50},[40,1071,725],{"class":50},[40,1073,1016],{"class":50},[40,1075,1056],{"class":50},[40,1077,1019],{"class":50},[40,1079,1080],{"class":92}," 53",[40,1082,1083],{"class":54},"                   # DNS queries\n",[40,1085,1086,1088,1090,1092,1094,1097,1099,1102,1104,1107],{"class":42,"line":99},[40,1087,719],{"class":46},[40,1089,1011],{"class":50},[40,1091,725],{"class":50},[40,1093,1016],{"class":50},[40,1095,1096],{"class":50}," -A",[40,1098,134],{"class":50},[40,1100,1101],{"class":92}," 0",[40,1103,1019],{"class":50},[40,1105,1106],{"class":92}," 80",[40,1108,1109],{"class":54},"               # print HTTP content as ASCII\n",[40,1111,1112,1114,1116,1118,1120,1122,1125,1127,1129],{"class":42,"line":116},[40,1113,719],{"class":46},[40,1115,1011],{"class":50},[40,1117,725],{"class":50},[40,1119,1016],{"class":50},[40,1121,489],{"class":50},[40,1123,1124],{"class":50}," capture.pcap",[40,1126,1019],{"class":50},[40,1128,859],{"class":92},[40,1130,1131],{"class":54},"     # write to a file for Wireshark\n",[40,1133,1134,1136,1138,1141],{"class":42,"line":128},[40,1135,719],{"class":46},[40,1137,1011],{"class":50},[40,1139,1140],{"class":50}," -r",[40,1142,1143],{"class":50}," capture.pcap\n",[15,1145,1146,1149,1150,1153,1154,1157],{},[19,1147,1148],{},"-nn"," skips resolving IPs and ports, so output is both faster and easier to read. If you see ",[19,1151,1152],{},"SYN"," packets leaving the client but no ",[19,1155,1156],{},"SYN-ACK"," coming back from the server, the problem is a firewall or security group in between.",[10,1159,1161],{"id":1160},"_8-firewalls","8. Firewalls",[31,1163,1165],{"className":33,"code":1164,"language":35,"meta":36,"style":36},"# firewalld (AlmaLinux \u002F RHEL)\nsudo firewall-cmd --list-all\nsudo firewall-cmd --permanent --add-port=8080\u002Ftcp\nsudo firewall-cmd --reload\n\n# ufw (Ubuntu)\nsudo ufw status verbose\nsudo ufw allow 8080\u002Ftcp\n\n# nftables \u002F iptables directly\nsudo nft list ruleset\nsudo iptables -L -n -v\n",[19,1166,1167,1172,1182,1194,1203,1209,1214,1226,1238,1242,1247,1260],{"__ignoreMap":36},[40,1168,1169],{"class":42,"line":43},[40,1170,1171],{"class":54},"# firewalld (AlmaLinux \u002F RHEL)\n",[40,1173,1174,1176,1179],{"class":42,"line":58},[40,1175,719],{"class":46},[40,1177,1178],{"class":50}," firewall-cmd",[40,1180,1181],{"class":50}," --list-all\n",[40,1183,1184,1186,1188,1191],{"class":42,"line":71},[40,1185,719],{"class":46},[40,1187,1178],{"class":50},[40,1189,1190],{"class":50}," --permanent",[40,1192,1193],{"class":50}," --add-port=8080\u002Ftcp\n",[40,1195,1196,1198,1200],{"class":42,"line":82},[40,1197,719],{"class":46},[40,1199,1178],{"class":50},[40,1201,1202],{"class":50}," --reload\n",[40,1204,1205],{"class":42,"line":99},[40,1206,1208],{"emptyLinePlaceholder":1207},true,"\n",[40,1210,1211],{"class":42,"line":116},[40,1212,1213],{"class":54},"# ufw (Ubuntu)\n",[40,1215,1216,1218,1221,1223],{"class":42,"line":128},[40,1217,719],{"class":46},[40,1219,1220],{"class":50}," ufw",[40,1222,386],{"class":50},[40,1224,1225],{"class":50}," verbose\n",[40,1227,1228,1230,1232,1235],{"class":42,"line":344},[40,1229,719],{"class":46},[40,1231,1220],{"class":50},[40,1233,1234],{"class":50}," allow",[40,1236,1237],{"class":50}," 8080\u002Ftcp\n",[40,1239,1240],{"class":42,"line":358},[40,1241,1208],{"emptyLinePlaceholder":1207},[40,1243,1244],{"class":42,"line":366},[40,1245,1246],{"class":54},"# nftables \u002F iptables directly\n",[40,1248,1249,1251,1254,1257],{"class":42,"line":380},[40,1250,719],{"class":46},[40,1252,1253],{"class":50}," nft",[40,1255,1256],{"class":50}," list",[40,1258,1259],{"class":50}," ruleset\n",[40,1261,1262,1264,1267,1269,1272],{"class":42,"line":392},[40,1263,719],{"class":46},[40,1265,1266],{"class":50}," iptables",[40,1268,467],{"class":50},[40,1270,1271],{"class":50}," -n",[40,1273,1274],{"class":50}," -v\n",[15,1276,1277,1278,1281],{},"On cloud servers, check the provider's ",[817,1279,1280],{},"security group \u002F cloud firewall"," rules in addition to the OS firewall.",[10,1283,1285],{"id":1284},"_9-step-by-step-checklist","9. Step-by-step checklist",[15,1287,1288,1291],{},[19,1289,1290],{},"https:\u002F\u002Fapi.example.com"," is unreachable:",[31,1293,1295],{"className":33,"code":1294,"language":35,"meta":36,"style":36},"dig +short api.example.com                      # 1. Does DNS return the right IP?\nnc -zv api.example.com 443                      # 2. Is the port open from outside?\ncurl -v https:\u002F\u002Fapi.example.com\u002Fhealth          # 3. What do TLS and HTTP return?\n# On the server:\nss -tlnp | grep -E ':443|:8080'                 # 4. Are Nginx and the app listening, on which address?\ncurl -s localhost:8080\u002Fhealth                   # 5. Does the app answer locally?\nsudo firewall-cmd --list-all                    # 6. Does the firewall allow it?\nsudo tail -n 50 \u002Fvar\u002Flog\u002Fnginx\u002Ferror.log        # 7. What does the proxy say?\njournalctl -u myapp -n 100                      # 8. What does the app say?\n",[19,1296,1297,1309,1323,1335,1340,1365,1377,1389,1406],{"__ignoreMap":36},[40,1298,1299,1301,1303,1306],{"class":42,"line":43},[40,1300,269],{"class":46},[40,1302,281],{"class":50},[40,1304,1305],{"class":50}," api.example.com",[40,1307,1308],{"class":54},"                      # 1. Does DNS return the right IP?\n",[40,1310,1311,1313,1315,1317,1320],{"class":42,"line":58},[40,1312,850],{"class":46},[40,1314,853],{"class":50},[40,1316,1305],{"class":50},[40,1318,1319],{"class":92}," 443",[40,1321,1322],{"class":54},"                      # 2. Is the port open from outside?\n",[40,1324,1325,1327,1329,1332],{"class":42,"line":71},[40,1326,131],{"class":46},[40,1328,455],{"class":50},[40,1330,1331],{"class":50}," https:\u002F\u002Fapi.example.com\u002Fhealth",[40,1333,1334],{"class":54},"          # 3. What do TLS and HTTP return?\n",[40,1336,1337],{"class":42,"line":82},[40,1338,1339],{"class":54},"# On the server:\n",[40,1341,1342,1344,1346,1349,1352,1355,1357,1360,1362],{"class":42,"line":99},[40,1343,163],{"class":46},[40,1345,658],{"class":50},[40,1347,1348],{"class":492}," |",[40,1350,1351],{"class":46}," grep",[40,1353,1354],{"class":50}," -E",[40,1356,541],{"class":492},[40,1358,1359],{"class":50},":443|:8080",[40,1361,702],{"class":492},[40,1363,1364],{"class":54},"                 # 4. Are Nginx and the app listening, on which address?\n",[40,1366,1367,1369,1371,1374],{"class":42,"line":116},[40,1368,131],{"class":46},[40,1370,134],{"class":50},[40,1372,1373],{"class":50}," localhost:8080\u002Fhealth",[40,1375,1376],{"class":54},"                   # 5. Does the app answer locally?\n",[40,1378,1379,1381,1383,1386],{"class":42,"line":128},[40,1380,719],{"class":46},[40,1382,1178],{"class":50},[40,1384,1385],{"class":50}," --list-all",[40,1387,1388],{"class":54},"                    # 6. Does the firewall allow it?\n",[40,1390,1391,1393,1396,1398,1400,1403],{"class":42,"line":344},[40,1392,719],{"class":46},[40,1394,1395],{"class":50}," tail",[40,1397,1271],{"class":50},[40,1399,241],{"class":92},[40,1401,1402],{"class":50}," \u002Fvar\u002Flog\u002Fnginx\u002Ferror.log",[40,1404,1405],{"class":54},"        # 7. What does the proxy say?\n",[40,1407,1408,1411,1414,1417,1419,1422],{"class":42,"line":358},[40,1409,1410],{"class":46},"journalctl",[40,1412,1413],{"class":50}," -u",[40,1415,1416],{"class":50}," myapp",[40,1418,1271],{"class":50},[40,1420,1421],{"class":92}," 100",[40,1423,1424],{"class":54},"                      # 8. What does the app say?\n",[748,1426,1427,1437],{},[751,1428,1429],{},[754,1430,1431,1434],{},[757,1432,1433],{},"Symptom",[757,1435,1436],{},"Likely cause",[766,1438,1439,1451,1460,1467,1478,1488],{},[754,1440,1441,1446],{},[771,1442,1443],{},[19,1444,1445],{},"Could not resolve host",[771,1447,1448,1449],{},"DNS record missing or wrong; check with ",[19,1450,269],{},[754,1452,1453,1457],{},[771,1454,1455],{},[19,1456,981],{},[771,1458,1459],{},"The service isn't running or wrong port",[754,1461,1462,1464],{},[771,1463,989],{},[771,1465,1466],{},"Firewall \u002F security group blocks it",[754,1468,1469,1472],{},[771,1470,1471],{},"Works locally, not from outside",[771,1473,1474,1475],{},"The app is bound to ",[19,1476,1477],{},"127.0.0.1",[754,1479,1480,1485],{},[771,1481,1482],{},[19,1483,1484],{},"SSL certificate problem",[771,1486,1487],{},"Expired certificate, incomplete chain or domain mismatch",[754,1489,1490,1498],{},[771,1491,1492,776,1495],{},[19,1493,1494],{},"502",[19,1496,1497],{},"504",[771,1499,1500],{},"The reverse proxy can't reach the app behind it, or it responds too slowly",[10,1502,1504],{"id":1503},"conclusion","Conclusion",[15,1506,1507,1508,1510,1511,146,1513,1515,1516,1519,1520,1523],{},"Nearly every network problem can be diagnosed with the dozen or so commands in this post. The key is to keep the order: DNS first (",[19,1509,269],{},"), then the port (",[19,1512,850],{},[19,1514,163],{},"), then the application (",[19,1517,1518],{},"curl -v","), and packets last (",[19,1521,1522],{},"tcpdump","). Each step narrows down where to look next and lets you isolate the problem in minutes instead of \"trying everything\".",[1525,1526,1527],"style",{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}",{"title":36,"searchDepth":58,"depth":58,"links":1529},[1530,1531,1532,1533,1534,1535,1536,1537,1538,1539,1540],{"id":12,"depth":58,"text":13},{"id":28,"depth":58,"text":29},{"id":167,"depth":58,"text":168},{"id":258,"depth":58,"text":259},{"id":423,"depth":58,"text":424},{"id":645,"depth":58,"text":646},{"id":839,"depth":58,"text":840},{"id":995,"depth":58,"text":996},{"id":1160,"depth":58,"text":1161},{"id":1284,"depth":58,"text":1285},{"id":1503,"depth":58,"text":1504},"2026-11-04","Finding out step by step why a service can't be reached — ip, ping, dig, curl, ss, traceroute\u002Fmtr, nc, tcpdump and firewall commands.","md",{},"\u002Fen\u002Fblog\u002Flinux-network-troubleshooting",{"title":5,"description":1542},"en\u002Fblog\u002Flinux-network-troubleshooting",[1549,1550,1551,1552],"linux","network","devops","guide","\u002Fblog\u002Flinux-network-troubleshooting","fZbVSFINZ4cr9uSRBxwN7HIPb0szgdq-nG8aLx22nrg",[1556,1564,1571],{"path":1557,"title":1558,"description":1559,"date":1560,"tags":1561},"\u002Fen\u002Fblog\u002Fssh-config-and-tunneling","SSH Config, Key Management and Tunneling","Generating ed25519 keys, ssh-agent, shortcuts with ~\u002F.ssh\u002Fconfig, jump hosts, port forwarding (-L, -R, -D) and server-side hardening.","2026-10-31",[1562,1549,1563,1552],"ssh","security",{"path":1565,"title":1566,"description":1567,"date":1568,"tags":1569},"\u002Fen\u002Fblog\u002Fsystemd-service-guide","Writing a Linux Service with systemd","Running an app as a systemd service — unit files, restart policies, environment variables, reading logs with journalctl, and scheduled jobs with timers.","2026-10-30",[1549,1570,1551,1552],"systemd",{"path":1572,"title":1573,"description":1574,"date":1575,"tags":1576},"\u002Fen\u002Fblog\u002Fgithub-actions-ci-cd","CI\u002FCD with GitHub Actions — Build, Test and Deploy to Your Server","A step-by-step GitHub Actions workflow that builds and tests on every push and deploys to your own server over SSH when changes land on main.","2026-10-29",[1577,1578,1551,1552],"github","ci-cd",1793754932096]