App Engine 服務的傳出 IP 位址

網址擷取、Sockets 和 Mail API 等傳出服務會運用大型的 IP 位址集區。這個集區中的 IP 位址範圍可能會進行例行性的變動。事實上,連續兩個來自相同應用程式的 API 呼叫看起來可能像是從不同 IP 位址發出。

如要查詢 App Engine 服務目前的 IP 位址範圍,請使用 Google 發布的兩個 JSON 檔案:

  • Google 會在 goog.json 中發布 Google 擁有的 IP 位址清單。

  • 此外,Google 也以 cloud.json 的格式發布了另一份清單,當中列出了客戶可在全球和特定區域內使用的外部 IP 位址範圍。 Google Cloud

goog.json 中移除所有 cloud.json 範圍,會產生大量 IP 位址,這些位址由全球 Google API 和其他 Google 服務使用,包括 Google Cloud以外的面向客戶產品。這些清單會定期更新。

您可以使用下列 Python 指令碼,建立包含 Google API 和服務所用 IP 位址的範圍清單。

如要瞭解如何執行這項指令碼,請參閱「如何執行」。

from __future__ import print_function

import json

try:
    from urllib import urlopen
except ImportError:
    from urllib.request import urlopen
    from urllib.error import HTTPError

import netaddr

IPRANGE_URLS = {
    "goog": "https://www.gstatic.com/ipranges/goog.json",
    "cloud": "https://www.gstatic.com/ipranges/cloud.json",
}


def read_url(url):
    try:
        return json.loads(urlopen(url).read())
    except (IOError, HTTPError):
        print("ERROR: Invalid HTTP response from %s" % url)
    except json.decoder.JSONDecodeError:
        print("ERROR: Could not parse HTTP response from %s" % url)


def get_data(link):
    data = read_url(link)
    if data:
        print("{} published: {}".format(link, data.get("creationTime")))
        cidrs = netaddr.IPSet()
        for e in data["prefixes"]:
            if "ipv4Prefix" in e:
                cidrs.add(e.get("ipv4Prefix"))
            if "ipv6Prefix" in e:
                cidrs.add(e.get("ipv6Prefix"))
        return cidrs


def main():
    cidrs = {group: get_data(link) for group, link in IPRANGE_URLS.items()}
    if len(cidrs) != 2:
        raise ValueError("ERROR: Could process data from Google")
    print("IP ranges for Google APIs and services default domains:")
    for ip in (cidrs["goog"] - cidrs["cloud"]).iter_cidrs():
        print(ip)


if __name__ == "__main__":
    main()