Python 一键扫描子域名
兄弟们,搞渗透测试或者资产收集的时候,扫子域名是基本功。今天给个纯Python方案,不依赖第三方工具,自己撸一个轻量级扫描器。
核心思路
用requests库发HTTP请求,配合字典爆破。简单粗暴,但够用。
代码实现
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import requests
import sys
from concurrent.futures import ThreadPoolExecutor, as_completed
from urllib3.exceptions import InsecureRequestWarning
# 关闭SSL警告
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
class SubdomainScanner:
def __init__(self, domain, wordlist, threads=20, timeout=3):
self.domain = domain
self.wordlist = wordlist
self.threads = threads
self.timeout = timeout
self.found = []
def check_subdomain(self, sub):
url = f"http://{sub}.{self.domain}"
try:
r = requests.get(url, timeout=self.timeout, verify=False,
headers={'User-Agent': 'Mozilla/5.0'})
if r.status_code < 400:
print(f"[+] {url} -> {r.status_code}")
return url
except:
pass
return None
def scan(self):
with open(self.wordlist, 'r') as f:
subs = [line.strip() for line in f if line.strip()]
print(f"[*] 开始扫描 {self.domain}")
print(f"[*] 字典数量: {len(subs)}")
print(f"[*] 线程数: {self.threads}")
with ThreadPoolExecutor(max_workers=self.threads) as executor:
futures = {executor.submit(self.check_subdomain, sub): sub for sub in subs}
for future in as_completed(futures):
result = future.result()
if result:
self.found.append(result)
print(f"\n[+] 扫描完成,发现 {len(self.found)} 个子域名")
if __name__ == "__main__":
if len(sys.argv) != 3:
print("用法: python subscan.py <domain> <wordlist>")
print("示例: python subscan.py example.com subdomains.txt")
sys.exit(1)
scanner = SubdomainScanner(sys.argv[1], sys.argv[2])
scanner.scan()
字典准备
搞个基础字典,按需扩充:
www
mail
admin
blog
ftp
dev
test
api
cdn
vpn
git
jenkins
wiki
forum
shop
使用方式
# 基本用法
python subscan.py example.com subdomains.txt
# 结果重定向
python subscan.py example.com subdomains.txt > result.txt
# 想更快?调线程
# 修改代码里的 threads=50
进阶玩法
- 加HTTPS支持:上面只扫HTTP,想扫HTTPS改一下url构造:
def check_subdomain(self, sub):
for scheme in ['http', 'https']:
url = f"{scheme}://{sub}.{self.domain}"
# 其他逻辑不变
- 结果导出:加个保存功能:
def save_result(self, filename):
with open(filename, 'w') as f:
for url in self.found:
f.write(url + '\n')
- 加CNAME解析:配合
socket.gethostbyname验证DNS解析,减少无效请求。
注意事项
- 别扫没授权的站,这是基本规矩
- 字典质量决定结果,建议用Seclists或者自己积累
- 线程数别太大,50以内够了,容易被封IP
- 生产环境建议加代理池和延时
对比其他工具
| 工具 | 速度 | 灵活性 | 依赖 |
|---|---|---|---|
| 这个脚本 | 中等 | 高 | 仅requests |
| subfinder | 快 | 中 | 需安装 |
| amass | 慢但全 | 低 | 需安装 |
小范围扫描用这个脚本够了,大项目还是上专业工具。
最后说一句,真正的老手都会自己改代码加功能。拿着这个改改,加个异步、加个多协议、加个结果去重,就变成自己的武器了。
💻 安全运维 / Linux运维 / 渗透测试 技术支持
业务需求可联系博客作者
