端口占用查看和网络监控

title

端口管理是Linux系统运维的重要组成部分。了解哪些端口被占用、被哪些进程使用,对于服务部署、故障排查和安全监控都至关重要。

基本端口查看命令

netstat命令

netstat是传统的网络统计工具,功能强大且广泛使用。

# 查看所有端口监听状态
netstat -tunlp

# 参数说明:
# -t: 显示TCP端口
# -u: 显示UDP端口  
# -n: 以数字形式显示地址和端口
# -l: 只显示监听状态的端口
# -p: 显示进程ID和进程名(需要root权限)

# 查看特定端口
netstat -tunlp | grep :80
netstat -tunlp | grep :22

# 查看所有网络连接
netstat -tuanp

# 查看TCP连接状态统计
netstat -ant | awk '{print $6}' | sort | uniq -c

ss命令

ss是现代Linux系统推荐的网络工具,性能比netstat更好。

# 查看所有监听端口
ss -tunlp

# 查看TCP监听端口
ss -tln

# 查看UDP监听端口  
ss -uln

# 查看特定端口
ss -tunlp | grep :80
ss -tunlp sport = :80

# 显示进程信息
ss -tlnp

# 查看连接统计
ss -s

lsof命令

lsof(List Open Files)可以查看指定端口的详细使用情况。

# 查看指定端口占用
lsof -i :80
lsof -i :22
lsof -i :3306

# 查看TCP端口
lsof -i tcp:80

# 查看UDP端口
lsof -i udp:53

# 查看指定进程的网络连接
lsof -i -p [PID]

# 查看指定用户的网络连接
lsof -i -u username

高级端口分析

端口扫描和服务识别

#!/bin/bash
# port_scanner.sh - 简单端口扫描脚本

TARGET=${1:-"localhost"}
START_PORT=${2:-1}
END_PORT=${3:-1000}

echo "扫描主机: $TARGET"
echo "端口范围: $START_PORT - $END_PORT"
echo "=============================="

for port in $(seq $START_PORT $END_PORT); do
    # 使用timeout避免长时间等待
    if timeout 1 bash -c "echo >/dev/tcp/$TARGET/$port" 2>/dev/null; then
        echo "端口 $port: 开放"

        # 尝试识别服务
        service=$(grep "^[^#]*\s$port/" /etc/services | head -1 | awk '{print $1}')
        if [ -n "$service" ]; then
            echo "  服务: $service"
        fi
    fi
done

端口使用分析脚本

#!/bin/bash
# port_analysis.sh - 端口使用情况分析

echo "系统端口使用分析报告"
echo "===================="
echo "生成时间: $(date)"
echo

echo "1. 监听端口统计:"
echo "---------------"
netstat -tln | awk 'NR>2 {print $4}' | cut -d: -f2 | sort -n | uniq -c | sort -nr | head -10

echo -e "\n2. 服务进程端口占用:"
echo "-------------------"
ss -tlnp | awk 'NR>1 {
    split($4, addr, ":")
    port = addr[length(addr)]
    if (port != "" && port != "*") {
        split($6, proc, ",")
        gsub(/.*pid=/, "", proc[1])
        gsub(/,.*/, "", proc[1])
        print port "\t" proc[1] "\t" $6
    }
}' | sort -n | head -20

echo -e "\n3. 网络连接状态统计:"
echo "-------------------"
netstat -ant | awk 'NR>2 {print $6}' | sort | uniq -c | sort -nr

echo -e "\n4. 外部连接统计(TOP 10):"
echo "----------------------"
netstat -ant | awk 'NR>2 && $6=="ESTABLISHED" {
    split($5, remote, ":")
    print remote[1]
}' | sort | uniq -c | sort -nr | head -10

echo -e "\n5. 常见服务端口检查:"
echo "------------------"
common_ports="22 23 25 53 80 110 143 443 993 995 3306 5432 6379 27017"
for port in $common_ports; do
    service=$(ss -tln | grep ":$port ")
    if [ -n "$service" ]; then
        process=$(ss -tlnp | grep ":$port " | awk '{print $6}' | cut -d, -f1)
        echo "端口 $port: 使用中 ($process)"
    else
        echo "端口 $port: 未使用"
    fi
done

实时端口监控

#!/bin/bash
# port_monitor.sh - 实时端口监控

LOG_FILE="/var/log/port_monitor.log"
CHECK_INTERVAL=60

monitor_ports() {
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')

    # 检查关键服务端口
    critical_ports="22 80 443 3306"

    for port in $critical_ports; do
        if ss -tln | grep -q ":$port "; then
            echo "[$timestamp] 端口 $port: 正常监听" >> $LOG_FILE
        else
            echo "[$timestamp] 警告: 端口 $port 未监听!" | tee -a $LOG_FILE
            # 这里可以添加告警通知
        fi
    done

    # 检查异常端口占用
    new_ports=$(ss -tln | awk 'NR>1 {split($4,a,":"); print a[length(a)]}' | sort -n | uniq)

    if [ -f /tmp/previous_ports.txt ]; then
        diff_ports=$(comm -13 /tmp/previous_ports.txt <(echo "$new_ports"))
        if [ -n "$diff_ports" ]; then
            echo "[$timestamp] 发现新端口: $diff_ports" | tee -a $LOG_FILE
        fi
    fi

    echo "$new_ports" > /tmp/previous_ports.txt
}

# 持续监控
while true; do
    monitor_ports
    sleep $CHECK_INTERVAL
done

端口安全分析

安全端口检查

#!/bin/bash
# security_port_check.sh - 端口安全检查

echo "端口安全检查报告"
echo "================"

echo "1. 危险端口检查:"
echo "---------------"
dangerous_ports="23 21 135 139 445 1433 3389 5900"
for port in $dangerous_ports; do
    if ss -tln | grep -q ":$port "; then
        echo "警告: 发现危险端口 $port 开放"
        case $port in
            23) echo "  - Telnet服务,建议使用SSH替代" ;;
            21) echo "  - FTP服务,建议使用SFTP替代" ;;
            135|139|445) echo "  - Windows共享服务,检查是否必要" ;;
            1433) echo "  - SQL Server,确保访问控制" ;;
            3389) echo "  - RDP服务,确保强密码和访问限制" ;;
            5900) echo "  - VNC服务,确保认证配置" ;;
        esac
    fi
done

echo -e "\n2. 对外开放端口检查:"
echo "-------------------"
ss -tln | awk 'NR>1 && $4 !~ /127\.0\.0\.1/ && $4 !~ /::1/ {
    split($4, addr, ":")
    port = addr[length(addr)]
    if (addr[1] == "0.0.0.0" || addr[1] == "::") {
        print "端口 " port ": 对外开放"
    }
}'

echo -e "\n3. 非标准端口服务:"
echo "-----------------"
ss -tlnp | awk 'NR>1 {
    split($4, addr, ":")
    port = addr[length(addr)]
    if (port > 1024 && port < 65535) {
        print "端口 " port ": " $6
    }
}' | head -10

echo -e "\n4. 建议:"
echo "-------"
echo "- 关闭不必要的服务和端口"
echo "- 使用防火墙限制端口访问"
echo "- 定期审计端口开放状况"
echo "- 监控异常端口活动"

网络连接异常检测

#!/bin/bash
# network_anomaly_detect.sh

echo "网络连接异常检测"
echo "================"

# 检测大量连接的IP
echo "1. 连接数异常IP (>50个连接):"
netstat -ant | awk '$6=="ESTABLISHED" {
    split($5, remote, ":")
    count[remote[1]]++
}
END {
    for (ip in count) {
        if (count[ip] > 50) {
            print ip ": " count[ip] " 连接"
        }
    }
}'

# 检测SYN_RECV状态过多
echo -e "\n2. SYN_RECV连接检查:"
syn_count=$(netstat -ant | grep SYN_RECV | wc -l)
if [ $syn_count -gt 100 ]; then
    echo "警告: SYN_RECV连接过多 ($syn_count),可能遭受SYN攻击"
else
    echo "SYN_RECV连接正常 ($syn_count)"
fi

# 检测TIME_WAIT状态
echo -e "\n3. TIME_WAIT连接检查:"
time_wait_count=$(netstat -ant | grep TIME_WAIT | wc -l)
if [ $time_wait_count -gt 1000 ]; then
    echo "警告: TIME_WAIT连接过多 ($time_wait_count)"
    echo "建议检查应用程序连接复用配置"
else
    echo "TIME_WAIT连接正常 ($time_wait_count)"
fi

# 检测异常端口连接
echo -e "\n4. 异常高端口连接:"
netstat -ant | awk '$6=="ESTABLISHED" {
    split($4, local, ":")
    split($5, remote, ":")
    if (remote[2] > 50000) {
        print "本地端口 " local[2] " -> " $5
    }
}' | head -5

防火墙集成

端口访问控制

#!/bin/bash
# port_firewall_manager.sh - 端口防火墙管理

PORT=$1
ACTION=$2
SOURCE_IP=$3

usage() {
    echo "用法: $0 <端口> <动作> [源IP]"
    echo "动作: open, close, allow, deny"
    echo "示例: $0 80 open"
    echo "     $0 22 allow 192.168.1.100"
    exit 1
}

if [ -z "$PORT" ] || [ -z "$ACTION" ]; then
    usage
fi

case $ACTION in
    "open")
        echo "开放端口 $PORT"
        iptables -A INPUT -p tcp --dport $PORT -j ACCEPT
        ;;
    "close")
        echo "关闭端口 $PORT"
        iptables -D INPUT -p tcp --dport $PORT -j ACCEPT 2>/dev/null
        iptables -A INPUT -p tcp --dport $PORT -j DROP
        ;;
    "allow")
        if [ -n "$SOURCE_IP" ]; then
            echo "允许 $SOURCE_IP 访问端口 $PORT"
            iptables -A INPUT -p tcp -s $SOURCE_IP --dport $PORT -j ACCEPT
        else
            echo "错误: 需要指定源IP"
            exit 1
        fi
        ;;
    "deny")
        if [ -n "$SOURCE_IP" ]; then
            echo "拒绝 $SOURCE_IP 访问端口 $PORT"
            iptables -A INPUT -p tcp -s $SOURCE_IP --dport $PORT -j DROP
        else
            echo "错误: 需要指定源IP"
            exit 1
        fi
        ;;
    *)
        echo "错误: 未知动作 $ACTION"
        usage
        ;;
esac

# 保存防火墙规则
echo "保存防火墙规则..."
iptables-save > /etc/iptables/rules.v4

故障排查

端口无法绑定问题

# 检查端口占用情况
check_port_binding() {
    local port=$1

    echo "检查端口 $port 绑定情况:"
    echo "======================="

    # 检查是否被占用
    if ss -tln | grep -q ":$port "; then
        echo "端口 $port 已被占用"

        # 显示占用进程
        echo "占用进程:"
        ss -tlnp | grep ":$port "

        # 显示进程详细信息
        pid=$(ss -tlnp | grep ":$port " | awk '{print $6}' | grep -o 'pid=[0-9]*' | cut -d= -f2)
        if [ -n "$pid" ]; then
            echo -e "\n进程详细信息:"
            ps -fp $pid
        fi
    else
        echo "端口 $port 未被占用"

        # 检查防火墙
        echo "检查防火墙规则:"
        iptables -L INPUT | grep -i "$port"
    fi
}

# 使用示例
# check_port_binding 80

网络服务诊断

#!/bin/bash
# network_service_diagnose.sh

SERVICE_PORT=$1

if [ -z "$SERVICE_PORT" ]; then
    echo "用法: $0 <端口号>"
    exit 1
fi

echo "网络服务诊断: 端口 $SERVICE_PORT"
echo "==============================="

# 1. 检查端口监听
echo "1. 端口监听状态:"
if ss -tln | grep -q ":$SERVICE_PORT "; then
    echo "  ✓ 端口正在监听"
    ss -tlnp | grep ":$SERVICE_PORT "
else
    echo "  ✗ 端口未监听"
fi

# 2. 检查进程状态
echo -e "\n2. 服务进程状态:"
pid=$(ss -tlnp | grep ":$SERVICE_PORT " | awk '{print $6}' | grep -o 'pid=[0-9]*' | cut -d= -f2)
if [ -n "$pid" ]; then
    echo "  进程ID: $pid"
    echo "  进程状态: $(ps -o stat= -p $pid)"
    echo "  启动时间: $(ps -o lstart= -p $pid)"
else
    echo "  未找到监听进程"
fi

# 3. 检查网络连接
echo -e "\n3. 网络连接测试:"
echo "  本地连接测试:"
if timeout 3 bash -c "echo >/dev/tcp/localhost/$SERVICE_PORT" 2>/dev/null; then
    echo "    ✓ 本地连接成功"
else
    echo "    ✗ 本地连接失败"
fi

# 4. 检查防火墙
echo -e "\n4. 防火墙检查:"
if command -v iptables >/dev/null; then
    fw_rules=$(iptables -L INPUT -n | grep -E ":$SERVICE_PORT |$SERVICE_PORT:")
    if [ -n "$fw_rules" ]; then
        echo "  防火墙规则:"
        echo "$fw_rules"
    else
        echo "  未找到特定防火墙规则"
    fi
fi

# 5. 日志检查
echo -e "\n5. 相关日志:"
echo "  最近的系统日志:"
journalctl --since "1 hour ago" | grep -i "$SERVICE_PORT" | tail -3

性能监控

端口性能统计

#!/bin/bash
# port_performance_stats.sh

echo "端口性能统计"
echo "============"

# 连接数统计
echo "1. 各端口连接数:"
netstat -ant | awk 'NR>2 && $6=="ESTABLISHED" {
    split($4, local, ":")
    count[local[2]]++
}
END {
    for (port in count) {
        print "端口 " port ": " count[port] " 个连接"
    }
}' | sort -k3 -nr | head -10

# 网络I/O统计
echo -e "\n2. 网络接口统计:"
cat /proc/net/dev | awk 'NR>2 {
    print $1 " 接收: " $2 " 字节, 发送: " $10 " 字节"
}' | head -5

# TCP状态分布
echo -e "\n3. TCP连接状态分布:"
netstat -ant | awk 'NR>2 {print $6}' | sort | uniq -c | sort -nr

注意事项和最佳实践

  1. 权限要求: 查看进程信息通常需要root权限
  2. 性能影响: 频繁的端口扫描可能影响系统性能
  3. 安全考虑:
    • 定期审计开放端口
    • 关闭不必要的服务
    • 使用防火墙限制访问
  4. 监控建议:
    • 建立端口基线
    • 监控异常连接
    • 定期安全检查

相关命令

  • netstat - 网络连接统计
  • ss - 现代网络工具
  • lsof - 列出打开文件
  • nmap - 网络扫描工具
  • iptables - 防火墙配置
  • tcpdump - 网络抓包
  • wireshark - 网络协议分析

掌握端口管理技能对于Linux系统运维、安全管理和故障排查都至关重要。


powered by Gitbook© 2025 编外计划 | 最后修改: 2025-07-28 12:47:16

results matching ""

    No results matching ""