OpenSSL C代码访问站点返回301 Moved Permanently问题排查
问题根因
你对现象的关联判断从一开始就是错的:三次test调用里,第一次访问的是openssl.org,后两次访问的是pastebin.com,是两个完全独立的站点,根本不存在“同一站点首次访问返回301、后续访问正常”的情况。
- 第一次调用返回301是
openssl.org站点自身的域名规范化配置:裸域openssl.org的所有请求,服务端都会永久301跳转到带www前缀的www.openssl.org对应路径,不管你用什么客户端、加什么请求头,这个跳转都存在,用浏览器直接访问也会触发,和Cloudflare、防火墙、反爬策略没有任何关系。 - 后两次访问
pastebin.com返回正常内容,是因为你请求的两个路径本身就是服务端存在的合法路径,且pastebin.com裸域没有配置强制跳转规则,自然不会返回301。 - 你之前加
User-Agent没有效果,是因为这个301根本不是防护策略触发的,就是站点最基础的域名跳转规则。
另外你代码里的HTTPS降级HTTP逻辑是完全无效的:BIO_set_conn_hostname() 这个API仅负责给SSL BIO设置目标主机、端口的内部参数,不会实际发起网络连接,也不会返回连接失败的结果,所以判断这个接口返回值小于0就降级创建HTTP连接的分支永远不会被触发,所有请求实际都是走HTTPS发起的。
代码现存隐患
你的代码还有几个会在后续场景出问题的缺陷:
- 没有配置SNI(服务器名称指示):你没有在SSL握手前调用
SSL_set_tlsext_host_name(ssl, host)设置要访问的域名,在访问Cloudflare这类同一IP承载多域名的CDN服务时,CDN无法识别你要访问的站点,很可能返回证书错误、默认站点内容甚至403响应。 - 没有实现自动跳转逻辑:标准HTTP客户端需要识别301/302/307/308响应的
Location头,自动向新地址发起请求,你当前的代码只会读取第一次响应的内容,遇到跳转就会直接把301响应原文输出,不会拿到目标内容。 - 存在内存泄漏:每次调用
test都会新建SSL_CTX上下文,但函数退出前没有调用SSL_CTX_free(ctx)释放资源,多次调用会持续泄漏内存。 - 存在栈溢出风险:所有字符串拼接都用了无长度校验的
sprintf,只要传入的域名、路径长度稍大,就会覆盖栈内存触发程序崩溃,建议替换成带长度限制的snprintf。
内容的提问来源于stack exchange,提问作者loaded_dypper
相关产品推荐
相关产品推荐

