Python3+OSX 10.13.2获取Facebook IP白名单时subprocess调用报错排查
解决OSX 10.13.2下用Python3调用subprocess获取Facebook ASN路由段的问题
看起来你在构建Facebook Webhook白名单时踩了OSX whois工具和subprocess参数传递的坑,我来帮你一步步理清问题并解决:
问题根源分析
- OSX whois与Linux的参数差异:你用的
-i origin AS32934是Linux系统whois(比如Ubuntu的whois)的专属参数,但OSX自带的whois不支持这个格式,这就是为什么会提示"-i后属性名无效或不支持"的核心原因。 - whois服务器未返回路由数据:OSX默认的whois服务器不会主动返回ASN对应的路由条目,必须指定专门的路由查询whois服务器才能拿到有效数据。
- subprocess的管道与退出码问题:当你拆分调用grep时,如果前面的whois输出没有匹配到"route",grep会返回退出码1,而
check_output/check_call默认会把非0退出码视为错误抛出CalledProcessError。
分步解决方案
1. 先在终端验证正确的whois命令
在OSX终端里,要获取AS32934(Facebook)的路由段,必须用以下命令:
whois -h whois.radb.net '!gAS32934'
这个命令指定了whois.radb.net(专门的路由查询服务器),用!gAS<ASN>的格式来查询该ASN的所有路由条目。执行后你应该能看到一堆以route:开头的行。
如果要过滤出纯路由条目,可以加上grep:
whois -h whois.radb.net '!gAS32934' | grep -i 'route:'
2. 在Python中用subprocess正确调用
推荐两种实现方式,优先选第一种(更安全,避免shell注入风险):
方式一:不用shell=True,用subprocess管道连接命令
import subprocess def get_facebook_routes(): try: # 第一步:调用whois获取AS32934的路由数据 whois_proc = subprocess.run( ['whois', '-h', 'whois.radb.net', '!gAS32934'], capture_output=True, text=True, check=True ) # 第二步:用grep过滤route行,设置check=False避免无匹配时报错 grep_proc = subprocess.run( ['grep', '-i', 'route:'], input=whois_proc.stdout, capture_output=True, text=True, check=False ) # 提取并整理路由IP段 routes = [line.split(':')[1].strip() for line in grep_proc.stdout.splitlines() if line.strip()] return routes except subprocess.CalledProcessError as e: print(f"whois命令执行出错: {e.stderr}") return []
方式二:用shell=True(简单但仅适合固定命令场景)
import subprocess def get_facebook_routes(): try: cmd = "whois -h whois.radb.net '!gAS32934' | grep -i 'route:'" output = subprocess.check_output(cmd, shell=True, text=True, stderr=subprocess.STDOUT) routes = [line.split(':')[1].strip() for line in output.splitlines() if line.strip()] return routes except subprocess.CalledProcessError as e: print(f"命令执行出错: {e.output}") return []
3. 构建FACEBOOK_WHITELIST
拿到路由列表后,可以用Python的ipaddress模块处理CIDR格式,方便后续验证请求IP:
import ipaddress # 获取Facebook路由段并转换为可验证的网络对象 FACEBOOK_ROUTES = get_facebook_routes() FACEBOOK_WHITELIST = [ipaddress.ip_network(route, strict=False) for route in FACEBOOK_ROUTES] # 验证示例:检查某个IP是否属于Facebook白名单 def is_facebook_ip(ip_str): try: ip = ipaddress.ip_address(ip_str) return any(ip in network for network in FACEBOOK_WHITELIST) except ValueError: return False
为什么之前的方法失败?
- 你用的
-i origin AS32934是Linux whois的专属参数,OSX whois不支持,换成指定whois.radb.net服务器和!gAS32934查询格式就解决了路由数据为空的问题。 - 之前的subprocess调用中,因为whois没有返回有效路由数据,导致grep找不到匹配项返回1,触发了
CalledProcessError,现在通过管道传递输入或设置check=False完美规避了这个问题。
内容的提问来源于stack exchange,提问作者joe
相关产品推荐
相关产品推荐

