0. 写在前面:为什么你需要“神器”而非“常用命令
大家好,欢迎来到干货、技术、专业全方位遥遥领先的老杨的博客.
帮老杨点赞、转发、在看以及打开小星标哦
攒今世之功德,修来世之福报
今天聊10块钱服务端口暴露这个事
干运维的应该都中过招吧.老杨当年就干过把Redis的6379端口到了公网,结果被人扫到了,数据库被清空了。
跟黑客相互攻防这事我可以再出几十篇博文.那可是老杨的高光时刻.记得有次去山东某央企背景做项目.到项目第二天项目就中招了.那时候也年轻,遇到这事还是挺兴奋了.就在那些甲方大小虾米不知所措.像开水里的泥鳅鱼四处乱串时.
咱哥们来了!迈着四方步来啦!算了,老杨啥实力?看看我那篇收费文章就知道了.
战略性吹嘘一把哈哈!算了有空给你多出一些深度文章,99%的同行没有遇到过真正的大事,遇到大事了99%都是认了,要么就是人力手动恢复的,很少有几个刺刀见红跟故障硬拼下来的.
咱还是回到今天的主题.
攻击者就像夜行的猎手,他们有一套完整的作案手法:
# 模拟的攻击者扫描过程
nmap -sS -O -p1-65535 target.company.com
Starting Nmap 7.94 ( https://nmap.org )
Nmap scan report for target.company.com (203.0.113.1)
Host is up (0.045s latency).
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
443/tcp open https
3306/tcp open mysql
6379/tcp open redis
...看到这个扫描结果,任何一个有经验的攻击者都会两眼放光。MySQL和Redis直接暴露在公网,这就像把银行金库的钥匙挂在门口一样。
国内企业最容易犯的几个错误:
数据库端口裸奔。很多公司为了开发方便,直接把MySQL的3306端口对外开放,以为设个复杂密码就安全了。实际上,暴力破解工具每分钟能尝试几千次密码,而且现在的攻击工具都很聪明,会结合社会工程学,用公司名、域名等信息生成密码字典。
远程桌面服务成了后门。Windows的RDP(3389端口)被攻破的案例我见过太多了,攻击者一旦拿到RDP权限,就等于拿到了服务器的完全控制权。
# 检查RDP是否对外开放的命令
netstat -an | findstr :3389
TCP 0.0.0.0:3389 0.0.0.0:0 LISTENING
TCP [::]:3389 [::]:0 LISTENING看到这个输出,说明RDP服务正在监听所有IP地址,这是非常危险的。
还有就是各种Web管理界面,比如phpMyAdmin、Redis-Commander这些,很多开发者为了管理方便,直接暴露在公网上,连基本的IP白名单都不设置。
# 攻击者常用的Web管理界面探测方法
curl -I http://target.com:8080/phpmyadmin/
HTTP/1.1 200 OK
Server: Apache/2.4.41
Content-Type: text/html; charset=utf-8
Set-Cookie: phpMyAdmin=abc123def456; path=/phpmyadmin/
...经过这些年的摸爬滚打,老杨总结出了一套比较实用的防护思路。
网络层防护是基础。防火墙规则要精细化配置,不能图省事就全部开放。我现在的习惯是,除了必要的80/443端口,其他端口都采用白名单策略。
# 我常用的iptables配置模板
iptables -F
iptables -X
iptables -t nat -F
# 默认策略:拒绝所有入站流量
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
# 允许本地回环
iptables -A INPUT -i lo -j ACCEPT
# 允许已建立的连接
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# SSH只允许内网访问
iptables -A INPUT -p tcp --dport 22 -s 192.168.1.0/24 -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -s 10.0.0.0/8 -j ACCEPT
# Web服务对外开放
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# 保存规则
service iptables save这套规则的思路很简单:默认拒绝,按需开放。SSH只允许内网IP访问,Web服务可以对外开放,但也要配合其他安全措施。
端口隐藏技术很有意思。Port Knocking(端口敲门)这个技术我觉得挺巧妙的,就像古代的暗号一样,只有知道正确序列的人才能打开服务。
# Port Knocking的配置文件
cat > /etc/knockd.conf << 'EOF'
[options]
UseSyslog
[openSSH]
sequence = 7000,8000,9000
seq_timeout = 5
command = /sbin/iptables -A INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
tcpflags = syn
[closeSSH]
sequence = 9000,8000,7000
seq_timeout = 5
command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
tcpflags = syn
EOF
systemctl enable knockd
systemctl start knockd客户端使用的时候就是这样:
knock server.company.com 7000 8000 9000 # 敲门开启SSH
ssh user@server.company.com # 正常SSH连接
knock server.company.com 9000 8000 7000 # 敲门关闭SSH这样配置后,除非知道正确的敲门序列,否则SSH端口对外是完全不可见的。
SSH安全配置这块我有很多经验。密码认证必须禁用,只用密钥认证。而且要用强密钥,我一般推荐ed25519算法:
# 生成强密钥对
ssh-keygen -t ed25519 -a 100 -f ~/.ssh/company_key -C "admin@company.com"
# 服务器端的安全配置
cat >> /etc/ssh/sshd_config << 'EOF'
# 禁用密码认证
PasswordAuthentication no
ChallengeResponseAuthentication no
# 只允许密钥认证
PubkeyAuthentication yes
# 限制登录用户
AllowUsers admin deploy
# 修改默认端口
Port 2222
# 禁用root登录
PermitRootLogin no
# 空闲超时设置
ClientAliveInterval 300
ClientAliveCountMax 2
EOF
systemctl restart sshd双因子认证(2FA)现在我也强烈推荐,尤其是重要的服务器。Google Authenticator配置起来也不复杂:
# 安装并配置
yum install -y google-authenticator
su - admin
google-authenticator
# 会出现类似这样的输出
Do you want authentication tokens to be time-based (y/n) y
Your new secret key is: ABCDEFGH12345678
Your verification code is 123456
Your emergency scratch codes are:
12345678
87654321
...
# SSH配置支持2FA
echo "auth required pam_google_authenticator.so" >> /etc/pam.d/sshd
sed -i 's/ChallengeResponseAuthentication no/ChallengeResponseAuthentication yes/' /etc/ssh/sshd_config
echo "AuthenticationMethods publickey,keyboard-interactive" >> /etc/ssh/sshd_config
systemctl restart sshd对于需要远程访问内网服务的场景,VPN是个不错的选择。WireGuard是我现在比较推荐的方案,性能好,配置也相对简单:
# 安装WireGuard
apt update && apt install -y wireguard
# 生成服务器密钥对
wg genkey | tee /etc/wireguard/server_private.key | wg pubkey > /etc/wireguard/server_public.key
# 服务器配置
cat > /etc/wireguard/wg0.conf << 'EOF'
[Interface]
PrivateKey = $(cat /etc/wireguard/server_private.key)
Address = 10.8.0.1/24
ListenPort = 51820
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
PublicKey = CLIENT_PUBLIC_KEY
AllowedIPs = 10.8.0.2/32
EOF
# 启用IP转发
echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf
sysctl -p
# 启动服务
systemctl enable wg-quick@wg0
systemctl start wg-quick@wg0WireGuard运行起来后,可以通过wg show命令查看连接状态:
wg show
interface: wg0
public key: ABC123...
private key: (hidden)
listening port: 51820
peer: DEF456...
allowed ips: 10.8.0.2/32
latest handshake: 1 minute, 23 seconds ago
transfer: 2.15 MB received, 1.87 MB sent这样配置后,所有需要访问内网服务的流量都会通过VPN隧道,大大提高了安全性。
光是做好防护还不够,还需要有敏锐的"电子哨兵"来实时监控。我自己写过一个端口监控脚本,分享给大家:
#!/bin/bash
# 我写的端口监控脚本
LOGFILE="/var/log/port_monitor.log"
WEBHOOK_URL="https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK"
# 要监控的端口
MONITORED_PORTS=(22 80 443 3306 6379)
get_open_ports() {
netstat -tuln | awk '/^tcp.*LISTEN/{print $4}' | cut -d: -f2 | sort -n
}
send_alert() {
local message="$1"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] ALERT: $message" >> $LOGFILE
# 发送到Slack
curl -X POST -H 'Content-type: application/json' \
--data "{\"text\":\"🚨 Port Monitor Alert: $message\"}" \
$WEBHOOK_URL
}
check_port_changes() {
local current_ports=$(get_open_ports)
local baseline_file="/tmp/baseline_ports.txt"
if [[ -f $baseline_file ]]; then
local baseline_ports=$(cat $baseline_file)
local new_ports=$(comm -13 <(echo "$baseline_ports") <(echo "$current_ports"))
local closed_ports=$(comm -23 <(echo "$baseline_ports") <(echo "$current_ports"))
if [[ -n $new_ports ]]; then
send_alert "发现新开放端口: $new_ports"
fi
if [[ -n $closed_ports ]]; then
send_alert "发现关闭端口: $closed_ports"
fi
fi
echo "$current_ports" > $baseline_file
}
# 检查高频连接
check_connection_frequency() {
local suspicious_ips=$(netstat -ntu | awk '/ESTABLISHED/{print $5}' | cut -d: -f1 | sort | uniq -c | awk '$1>10{print $2}')
if [[ -n $suspicious_ips ]]; then
send_alert "发现高频连接IP: $suspicious_ips"
fi
}
while true; do
check_port_changes
check_connection_frequency
sleep 60
done这个脚本的核心思路是建立端口基线,一旦发现异常变化就立即告警。在实际使用中,老杨会配合企业微信或者钉钉的Webhook,确保告警能及时到达。
简单聊一下,还有很多企业实战、ai驱动等等一系列高端操作我们以后慢慢聊,但是搞了这么多年运维,老杨最大的感悟是:安全工作没有一劳永逸的解决方案,需要持续地投入和改进。技术在发展,攻击手法也在不断演进,我们需要保持学习的心态。
端口安全只是整个安全体系的一个环节,但确实是很关键的一环。乡亲们之前遇到啥事了可以评论区一起聊聊.我也看看大拿们有没有跟我一个遭遇的.
这里老杨先声明一下,日常生活中大家都叫老杨波哥,跟辈分没关系,主要是岁数大了.就一个代称而已. 老杨的00后小同事老杨喊都是带哥的.张哥,李哥的. 但是这个称呼呀,在线下参加一些活动时.金主爸爸也这么叫就显的不太合适. 比如上次某集团策划总监,公司开大会来一句:“今个咱高兴!有请IT运维技术圈的波哥讲两句“ 这个氛围配这个称呼在互联网这行来讲就有点对不齐! 每次遇到这个情况老杨老杨周末浅聊服务器开在公网的那些坑老杨干了,你们随意!” 所以以后咱们改叫老杨,即市井又低调.还挺亲切,老杨觉得挺好.
运维X档案系列文章:
企业级 Kubernetes 集群安全加固全攻略( 附带一键检查脚本)
看完别走.修行在于点赞、转发、在看.攒今世之功德,修来世之福报
老杨AI的号: 98dev