Firewall commands: is the port open, and how do I open it?
When the address is right, the route is right and DNS works, the last place a connection dies is a firewall: on your machine, on the far machine, or in between. Here is how to look at each, and the one test that tells you which.
First, find out where it is blocked
- Is anything listening? On the server:
ss -tlnp | grep :8080,netstat -ano | findstr :8080,lsof -iTCP:8080 -sTCP:LISTEN. If nothing is, no firewall rule will help. Check it listens on0.0.0.0or*, not only127.0.0.1. Details → - Does it work from the server itself?
curl -v http://127.0.0.1:8080/ornc -zv 127.0.0.1 8080. If not, the application is the problem. - Does it work from the same LAN?
Test-NetConnection 192.168.1.10 -Port 8080ornc -zv 192.168.1.10 8080from another machine. If not, it is the host firewall on the server (this page). - Does it work from the internet? If LAN works and internet does not, it is the router's NAT/port forwarding, a CGNAT ISP, or a cloud security group, not the host.
- Watch it arrive.
tcpdump -i eth0 -n 'tcp port 8080'on the server while connecting: SYN arrives but no reply means the host firewall dropped it; nothing arrives means it never got there. Capture guide →
Windows Defender Firewall
netsh advfirewall show allprofiles :: state of Domain, Private, Public profiles
netsh advfirewall show currentprofile
netsh advfirewall firewall show rule name=all | findstr /i "Rule Name Enabled Direction LocalPort"
netsh advfirewall firewall show rule name="Allow 8080"
:: allow inbound TCP 8080 (admin)
netsh advfirewall firewall add rule name="Allow 8080" dir=in action=allow protocol=TCP localport=8080
:: only from the LAN
netsh advfirewall firewall add rule name="Allow 8080 LAN" dir=in action=allow protocol=TCP localport=8080 remoteip=192.168.1.0/24 profile=private
:: allow a program instead of a port
netsh advfirewall firewall add rule name="MyApp" dir=in action=allow program="C:\Apps\myapp.exe" enable=yes
:: allow ping (ICMP echo)
netsh advfirewall firewall add rule name="Allow ICMPv4 echo" protocol=icmpv4:8,any dir=in action=allow
:: block an outbound destination
netsh advfirewall firewall add rule name="Block host" dir=out action=block remoteip=203.0.113.5
:: delete
netsh advfirewall firewall delete rule name="Allow 8080"
:: turn off/on (testing only)
netsh advfirewall set allprofiles state off
netsh advfirewall set allprofiles state on
:: reset to defaults
netsh advfirewall reset
:: log dropped packets to %systemroot%\system32\LogFiles\Firewall\pfirewall.log
netsh advfirewall set allprofiles logging droppedconnections enableGet-NetFirewallProfile | Format-Table Name, Enabled, DefaultInboundAction, DefaultOutboundAction
Get-NetFirewallRule -Enabled True -Direction Inbound -Action Allow | Format-Table DisplayName, Profile
Get-NetFirewallRule -DisplayName "*8080*" | Get-NetFirewallPortFilter
# which rules apply to a port
Get-NetFirewallPortFilter | Where-Object LocalPort -eq 8080 | Get-NetFirewallRule | Format-Table DisplayName, Enabled, Direction, Action
New-NetFirewallRule -DisplayName "Allow 8080" -Direction Inbound -Protocol TCP -LocalPort 8080 -Action Allow -Profile Private,Domain
New-NetFirewallRule -DisplayName "Allow ICMPv4" -Protocol ICMPv4 -IcmpType 8 -Direction Inbound -Action Allow
Set-NetFirewallRule -DisplayName "Allow 8080" -Enabled False
Remove-NetFirewallRule -DisplayName "Allow 8080"
Set-NetFirewallProfile -Profile Public -Enabled False # testing only
Get-NetConnectionProfile # is this network Public or Private? Public blocks almost everything inbound
Set-NetConnectionProfile -InterfaceAlias Ethernet -NetworkCategory PrivateThe most common Windows surprise is a network classed as Public: file sharing, ping and most inbound rules are then off regardless of what you add. The second is a third-party security suite replacing Defender Firewall; its rules live in its own console. wf.msc opens the graphical console.
Linux
Which one you have: ufw on Ubuntu and Debian derivatives, firewalld on Fedora, RHEL, Rocky, Alma and openSUSE, raw nftables or iptables on Arch, Alpine, containers and older systems. All of them end up as nftables (or iptables) rules in the kernel, so nft list ruleset shows the truth whichever front end you use.
sudo ufw status verbose
sudo ufw status numbered
sudo ufw allow 8080/tcp
sudo ufw allow from 192.168.1.0/24 to any port 8080 proto tcp
sudo ufw allow ssh # by service name from /etc/services
sudo ufw allow 60000:61000/udp # a range (mosh)
sudo ufw deny 23
sudo ufw delete allow 8080/tcp
sudo ufw delete 3 # by number from 'status numbered'
sudo ufw limit ssh # rate-limit connection attempts
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw enable
sudo ufw disable # testing only
sudo ufw logging on; sudo tail -f /var/log/ufw.log
sudo ufw resetsudo firewall-cmd --state
sudo firewall-cmd --get-active-zones
sudo firewall-cmd --list-all # default zone: services, ports, sources
sudo firewall-cmd --zone=public --list-all
sudo firewall-cmd --add-port=8080/tcp # runtime only
sudo firewall-cmd --permanent --add-port=8080/tcp # persistent
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-rich-rule='rule family=ipv4 source address=192.168.1.0/24 port port=8080 protocol=tcp accept'
sudo firewall-cmd --permanent --remove-port=8080/tcp
sudo firewall-cmd --reload # apply permanent changes
sudo firewall-cmd --runtime-to-permanent
sudo firewall-cmd --get-services
sudo firewall-cmd --zone=home --change-interface=enp3s0
sudo firewall-cmd --panic-on # drop everything (emergency)
sudo systemctl stop firewalld # testing onlysudo nft list ruleset # everything, whatever front end created it
sudo nft list table inet filter
sudo nft list chain inet filter input
# a minimal stateful firewall
sudo nft add table inet filter
sudo nft add chain inet filter input '{ type filter hook input priority 0; policy drop; }'
sudo nft add rule inet filter input ct state established,related accept
sudo nft add rule inet filter input iif lo accept
sudo nft add rule inet filter input tcp dport { 22, 8080 } accept
sudo nft add rule inet filter input icmp type echo-request accept
sudo nft add rule inet filter input icmpv6 type { echo-request, nd-neighbor-solicit, nd-neighbor-advert, nd-router-advert } accept
# delete a rule: list with handles, then delete by handle
sudo nft -a list chain inet filter input
sudo nft delete rule inet filter input handle 7
# persist
sudo nft list ruleset > /etc/nftables.conf # Debian/Ubuntu; enable nftables.service
sudo nft flush ruleset # remove everything (testing only)sudo iptables -L -n -v --line-numbers # filter table, numeric, with counters
sudo iptables -t nat -L -n -v # NAT table (Docker, port forwarding)
sudo ip6tables -L -n -v
sudo iptables -A INPUT -p tcp --dport 8080 -j ACCEPT
sudo iptables -I INPUT 1 -p tcp --dport 8080 -s 192.168.1.0/24 -j ACCEPT # insert at the top
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A INPUT -p icmp -j ACCEPT
sudo iptables -D INPUT -p tcp --dport 8080 -j ACCEPT # delete a matching rule
sudo iptables -D INPUT 3 # delete by number
sudo iptables -P INPUT DROP # default policy (add ESTABLISHED and ssh rules first!)
sudo iptables-save > /etc/iptables/rules.v4 # persist (iptables-persistent / netfilter-persistent)
sudo iptables -F # flush all rules (testing only; with policy DROP this locks you out)
# on modern kernels 'iptables' is iptables-nft, a translation layer over nftablesDocker adds its own chains (DOCKER, DOCKER-USER) that bypass ufw for published ports; put restrictions in the DOCKER-USER chain. Cloud VMs additionally have a provider firewall (AWS security groups, Azure NSGs, GCP firewall rules, Hetzner/DigitalOcean cloud firewalls) that the guest cannot see; check the console when a port stays closed despite correct guest rules.
macOS
Two layers: the application firewall (System Settings › Network › Firewall) which allows or blocks per app, and pf, the BSD packet filter, off by default and used by some VPN and security products.
# application firewall
/usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstate
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setglobalstate on
/usr/libexec/ApplicationFirewall/socketfilterfw --listapps
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --add /Applications/MyApp.app
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --unblockapp /Applications/MyApp.app
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setstealthmode on # ignore ping
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setblockall off
# pf
sudo pfctl -s info # enabled?
sudo pfctl -s rules
sudo pfctl -s nat
sudo pfctl -s states
sudo pfctl -e # enable
sudo pfctl -d # disable
sudo pfctl -f /etc/pf.conf # load rules
sudo pfctl -nf /etc/pf.conf # syntax check only
# a custom anchor with a rule, without editing the system pf.conf:
echo 'pass in proto tcp from 192.168.1.0/24 to any port 8080' | sudo pfctl -a com.local.custom -f -
sudo pfctl -a com.local.custom -s rulesSigned apps from the App Store and Apple are allowed inbound automatically; a self-built server binary is what usually triggers the "allow incoming connections?" dialog, and blocking it there is the usual reason a Mac cannot be reached on a port that is definitely listening.
Test a port from the other side
Test-NetConnection 192.168.1.10 -Port 8080 # PowerShell: TcpTestSucceeded True/False
nc -zv 192.168.1.10 8080 # macOS/Linux
nc -zvu 192.168.1.10 53 # UDP (a missing reply proves nothing)
curl -v telnet://192.168.1.10:8080
nmap -p 8080 192.168.1.10 # open / closed / filtered
nmap -sU -p 53 192.168.1.10nmap's three answers are the useful part: open (a service answered), closed (the host replied with a reset: reachable, nothing listening, no firewall in the way), filtered (no reply at all: a firewall dropped it somewhere). Windows hosts with the firewall on show filtered for everything they do not allow.
Router port forwarding
For a service reachable from the internet you also need the router to forward the port to the host's LAN address (Port Forwarding, Virtual Server, NAT rules, Games & Applications). Give the host a reserved address first, forward TCP and/or UDP as needed, then test from outside your network (a phone on mobile data). If your router's WAN address is in 100.64.0.0/10 or a private range, you are behind carrier-grade NAT and forwarding cannot work; see CGNAT. UPnP lets applications open ports automatically; many people prefer to disable it and forward by hand.