技术 · 2024 年 12 月 12 日 1

解决部分苹果iCloud+用户访问网站出现的403错误:iCloud专用代理与搜索引擎IP的自动配置

问题背景

最近,有少量用户反馈无法访问我们的网站,经过排查,发现他们的IP地址被识别为非允许访问的范围,导致出现403错误。进一步分析后,发现用户的IP地址来自于Cloudflare的主机IP段,这引起了我们的疑惑。

Cloudflare的IP通常用于CDN和反向代理,很少有普通用户直接使用。经过研究,我们发现这与Apple的iCloud+订阅服务中的“专用代理”功能有关。该功能类似于VPN,会使用户的流量通过苹果的服务器进行转发。

苹果官方提供了关于此功能的详细信息以及IP地址列表:

我们查看了苹果提供的IP列表,发现其中包含了大量的IP CIDR地址,仅日本(JP)地区的IP CIDR就有6000多行。为了解决这个问题,我们需要自动化地获取并配置这些IP,以及其他搜索引擎的IP地址。

解决方案:使用脚本自动获取和配置IP列表

为了简化管理和减少手动操作,我编写了一个bash脚本,该脚本使用 Python3 来自动获取以下IP列表,并将其配置到我们的服务器中:

  1. 日本原生IP: 从APNIC获取日本地区的IP段信息。
  2. iCloud专用代理IP: 从苹果官方API获取iCloud专用代理的IP列表,并筛选出日本地区的IP。
  3. 搜索引擎IP: 获取Google, Bing, OpenAI和Cloudflare的IP列表,以便于搜索引擎爬虫正常访问。

以下是脚本的具体内容和步骤:

#!/bin/bash

# 配置日本IP列表
configure_japan_ips() {
    echo "正在配置日本IP列表..."

    # 安装 Python3 和必要的系统包
    apt install -y python3-full python3-pip python3-requests || handle_error "Python包安装失败"

    # 创建日本IP获取脚本
    cat > /root/jpip.py = 7 and parts[1] == 'JP' and (parts[2] == 'ipv4' or parts[2] == 'ipv6'):
                    ip = parts[3]
                    if parts[2] == 'ipv4':
                        count = int(parts[4])
                        prefix = 32 - int(math.log2(count))
                    else:  # ipv6
                        prefix = parts[4]
                    japan_ips.add(f"Require ip {ip}/{prefix}")

        # 处理iCloud数据
        with open('/root/egress-ip-ranges.csv', 'r') as f:
            for line in f:
                try:
                    ip_range, country, region, city, *_ = line.strip().split(',')
                    if country == 'JP':
                        japan_ips.add(f"Require ip {ip_range}")
                except:
                    continue

        # 添加搜索引擎IP下载
        download_search_engine_ips()

        # 确保输出目录存在
        output_path = Path(f"/root/jpip.conf")
        output_path.parent.mkdir(parents=True, exist_ok=True)

        # 保存到文件
        with open(output_path, 'w') as f:
            f.write('\n'.join(sorted(japan_ips)))

        print(f"成功保存 {len(japan_ips)} 条 IP 记录到 {output_path}")
        return 0

    except Exception as e:
        print(f"错误: {str(e)}", file=sys.stderr)
        return 1

if __name__ == '__main__':
    sys.exit(main())
EOF

    # 设置执行权限
    chmod +x /root/jpip.py || handle_error "设置脚本权限失败"

    echo "开始运行 jpip.py 脚本..."
    python3 /root/jpip.py || handle_error "日本IP列表获取失败"

    echo "删除临时文件"
    rm -rf /root/delegated-apnic-latest
    rm -rf /root/egress-ip-ranges.csv
    rm -rf /root/jpip.py
    sleep 2

    echo "设置每周定时运行"
    if ! grep -q "^0 0 \* \* 0 /root/jpip\.sh" /etc/crontab; then
        echo "0 0 * * 0 /root/jpip.sh" >> /etc/crontab
        systemctl restart cron
        echo "已添加定时任务"
    else
        echo "定时任务已存在,跳过添加"
    fi
    sleep 2

    echo "重启apache2"
    systemctl restart apache2
    sleep 2

    echo "配置完成" 
    sleep 2
}

# 主函数
main() {
    # 检查root权限
    [ "$(id -u)" != "0" ] && handle_error "请使用root权限运行此脚本"

    configure_japan_ips
}

main

脚本说明

  1. 错误处理: 使用 handle_error 函数统一处理错误,方便调试。
  2. 安装依赖: 自动安装 python3-full, python3-pippython3-requests
  3. Python脚本 (/root/jpip.py):
    • 使用 requests 库下载 APNIC 数据,iCloud IP列表和搜索引擎的IP列表。
    • 解析 APNIC 数据,筛选出日本地区的 IPv4 和 IPv6 地址,并计算前缀长度。
    • 解析 iCloud IP 列表,筛选出日本地区的 IP 段。
    • 下载并解析Google, Bing, OpenAI和Cloudflare的IP列表。
    • 将所有IP地址保存到 /root/jpip.conf/root/searchip.conf 文件中。
  4. 脚本执行:
    • 设置 Python 脚本的执行权限。
    • 执行 Python 脚本,获取并保存 IP 地址。
    • 删除临时文件。
    • 设置定时任务,每周日凌晨0点自动更新 IP 地址列表。
    • 重启 apache2 使配置生效。

使用方法

  1. 将上述脚本保存为 /root/jpip.sh
  2. 赋予执行权限:chmod +x /root/jpip.sh
  3. 以 root 用户运行脚本:bash /root/jpip.sh
  4. 脚本运行后,会在 /root/ 目录下生成 jpip.conf 文件,该文件包含了所有需要允许访问的IP地址。以及 /root/searchip.conf 包含搜索引擎的IP地址。
  5. 根据实际情况,将/root/jpip.conf/root/searchip.conf文件中的内容配置到你的Web服务器(如Apache或Nginx)的IP访问控制规则中。
  • 例如在Apache中你可以使用Require ip指令。

结论

通过使用该脚本,我们能够自动获取并更新日本地区的原生IP、iCloud专用代理IP以及搜索引擎IP列表。这样,既可以解决由于iCloud专用代理导致的访问问题,同时也能保证搜索引擎爬虫的正常访问。

希望这篇文章能够帮助你解决类似的问题。如有任何疑问,请随时留言。