惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Y
Y Combinator Blog
D
Docker
有赞技术团队
有赞技术团队
D
DataBreaches.Net
The GitHub Blog
The GitHub Blog
爱范儿
爱范儿
H
Help Net Security
美团技术团队
MyScale Blog
MyScale Blog
B
Blog RSS Feed
C
Check Point Blog
Microsoft Security Blog
Microsoft Security Blog
阮一峰的网络日志
阮一峰的网络日志
A
About on SuperTechFans
小众软件
小众软件
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
GbyAI
GbyAI
G
Google Developers Blog
月光博客
月光博客
Google DeepMind News
Google DeepMind News
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Blog — PlanetScale
Blog — PlanetScale
MongoDB | Blog
MongoDB | Blog
F
Fortinet All Blogs

Dallas Lu

一些没有意义的事情 博客程序的一次大重构 OpenWRT 使用 udp2raw 对抗 WireGuard 阻断 如何证明你是原创作者 Nginx 泛域名配置的隐患与对策 WISeID S/MIME 证书 V2EX 刑满释放记 使用 Radicale 在 Ubuntu 24.04 中搭建 vCards CardDav 服务 邮件服务的域名成功从 SURBL 黑名单移除 网站多语言的设计细节 网站评论系统的目前进展和展望 在公网使用 iptables 转发端口时保留客户端 IP 邮件投递平台 Postal 的使用经验 自建 Postal 完美替代 SendGrid 互联网在崩塌吗,然后呢 在 SvelteKit 应用中使用 JSON-LD 网页的打印样式应该怎么写 “茴字的四种写法”之 IP 与域名 怎么伪造 Git 提交的时区 供大众交流的论坛和其它替代产品还是不好用
Wildcard-domajna agordo en Nginx: riskoj kaj kontraŭrimedoj
达拉斯・卢 · 2025-05-23 · via Dallas Lu

La programo de retejo subtenas plurlokan reĝimon, do pro oportunecon oni agordis la domajnon *.example.com en Nginx. Tamen, strangaj subdomajnoj ofte aperas en la alirregistroj, kio kaŭzas senton de malkonveno. Ĉi tiu artikolo priskribas kiel uzi Nginx por eviti tian riskon.

Wildcard-domajna ligado

Origina agordo de Nginx aspektas tiel:

server {
    listen 80;
    server_name *.example.com;

    // blabla
}

Tia agordo estas simpla kaj oportuna. Tamen, se via retejo ne efektive subtenas plurlokan reĝimon, aŭ se la programo ne ĝuste traktas la domajnojn, ĉiu ajn subdomajno povos aliri la enhavon — kio estas iom strange.

Eble iu konscie konstruas kaj publikigas nekutiman ligilon, kiu hazarde estas kaptita de ret-robotoj. Imagu vizitantojn venantajn el tiaj fontoj, mirantajn pri la stranga subdomajno — tio estas neintencita konduto, kun ebla SEO-damaĝo kaj konformeca risko. Oni devus adopti rimedojn por eviti tion.

Se la nombro de subdomajnoj estas limigita, listigu ilin rekte:

server {
    listen 80;
-    server_name *.example.com;
+    server_name
+        www.example.com
+        cdn.example.com
+        api.example.com;
}

Se via bezono estas pli kompleksa kaj vi volas konservi *.example.com, vi povas aldoni blanklistan kontrolon:

En Nginx, $server_name estas la unua valoro listigita en server_name, do metu la ĉefan domajnon unue por pli facila traktado.

Se vi antaŭe uzis blog.example.com, sed nun revenis al www.example.com, la plej taŭga maniero estas redirekti. Ĉiuj aliaj neatenditaj domajnoj povas esti tuj fermitaj per return 444;.

server {
    listen 80;
-    server_name *.example.com;
+    server_name www.example.com example.com *.example.com;
+
+    if ($host ~* ^((blog|feed|log)\.example\.com|example.com)$) {
+        return 307 $scheme://$server_name$request_uri;
+    }
+
+    if ($host !~* ^(cdn|api)\.example\.com$) {
+        return 444;
+    }
}

Defaŭlta gastiganto

Ankaŭ defaŭltaj serviloj havas riskojn. Se ne-registrita domajno indikas al via IP-adreso, en Ĉinio tio povus kontraui regulojn. Por tio, malakceptu ĉion krom laŭ-IP-aliron:

server {
    listen 80 default_server;
    server_name _;

    return 444;
}

Por permesi rektan IP-aliron:

-return 444;
+if ($host !~* "^((?:\d{1,3}\.){3}\d{1,3}|(?:[a-fA-F0-9:]+))$") {
+    return 444;
+}

SNI-revelacio en HTTPS

Eĉ se konekto estas malakceptita, en HTTPS la TLS-certifikato ankoraŭ povas reveli domajnojn per SNI (Server Name Indication). Por tio:

+ssl_reject_handshake on;

Se vi volas permesi IP-bazitan HTTPS, vi bezonas IP-specifan SSL-atestilon. Vi povas memsigni tian:

IPv4-certifikato

openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout ip.key -out ip.crt \
  -subj "/CN=1.2.3.4" \
  -addext "subjectAltName=IP:1.2.3.4"

IPv6-subteno

Uzu openssl-san.conf:

[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no

[req_distinguished_name]
CN = (ip or domain or keep bank)

[v3_req]
subjectAltName = @alt_names

[alt_names]
IP.1 = 1.2.3.4
IP.2 = 2001:db8::1
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout ip-mixed.key -out ip-mixed.crt \
  -config openssl-san.conf

Nginx-agordo:

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    listen 443 ssl default_server;
    listen [::]:443 ssl default_server;

    server_name _;

    ssl_certificate /path/to/ip.crt;
    ssl_certificate_key /path/to/ip.key;

    if ($host !~* "^((?:\d{1,3}\.){3}\d{1,3}|(?:[a-fA-F0-9:]+))$") {
        return 444;
    }
}

Eviti ke CDN-domajno estu indeksita

    root /path/to/webroot/www.example.com;

    location = /robots.txt {
        default_type text/plain;

        if ($host = 'cdn.example.com') {
            #return 200 "User-agent: *\nAllow: /*.png$\nDisallow: /\n";
            alias /path/to/webroot/www.example.com/robots-cdn.txt;
        }
    }