• Bryton Lacquement's avatar
    powerdns: update GeoIP backend configuration · 214e1399
    Bryton Lacquement authored
    With the recent powerdns upgrade, the GeoIP backend uses a new config
    format, see zones-file.yml.jinja2.
    
    zz.countries.nexedi.dk.rbldnsd (which maps IPs to countries) is replaced
    by GeoLite2-Country.mmdb(1) (which maps IPs to countries & continents).
    
    Note: zz.countries.nexedi.dk.rbldnsd is not deleted (yet?); it is parsed
    to keep information about China and its IP ranges grouped by ISP.
    
    cdn.conf.in (which maps RR(s) to countries) is dropped; it is replaced
    by an equivalent mapping done inside zones-file.yml.jinja2.
    
    Also, EDNS Client Subnet extension is enabled.
    
    ---
    (1): Added in previous commit.
    214e1399
zones-file.yml.jinja2 3.81 KB
# See https://doc.powerdns.com/authoritative/backends/geoip.html

{%- set slave_instance_list = json_module.loads(slapparameter_dict.get('extra_slave_instance_list', '[]')) %}
{%- set zone = slapparameter_dict.get('zone', 'example.com') %}

{%- macro disambiguate_domain_name(a, b) %}
{#- See http://www.dns-sd.org/trailingdotsindomainnames.html #}
{%- if a.endswith('.') %}
{{- a[:-1] }}
{%- else %}
{{- a }}.{{ b }}
{%- endif %}
{%- endmacro %}

domains:
- domain: {{ zone }}
  # TODO: what value for ttl?
  ttl: 300

  # Note: For each domain, one record of the domain name MUST exist with a soa record.
  records:
    {{ zone }}:
      - soa: {{ slapparameter_dict.get('soa', 'ns0.example.com,admin@example.com').replace(',', ' ') }}
      {%- for ns in slapparameter_dict.get('ns-record', 'ns0.example.com,ns1.example.com').split(',') %}
      - ns: {{ ns }}
      {%- endfor %}

    {#- Split the world the way we prefer. 'GeoLite2-Country.mmdb' divides the
        world into 7 continents: Oceania, Asia, Europe, South America,
        North America, Africa and Antarctica. However, we also want a more
        fine-grained division for Asia, i.e. West/East, China, Hong-Kong and
        Japan. #}
    {%- set world_split = {
          "continent": {
            "eu": "europe",
            "af": "africa",
            "sa": "south-america",
            "na": "north-america",
            "oc": "oceania",
          },
          "country": {}} %}

    {%- for region, codes in asia.items() %}
    {%-   for country_code in codes.split() %}
    {%-     do world_split["country"].__setitem__(country_code, region) %}
    {%-   endfor %}
    {%- endfor %}

    {%- for slave in slave_instance_list %}

    {#-   Set the RR to use for each region, as described in
          'slave-instance-powerdns-input-schema.json' #}
    {%-   set rr_dict = {} %}
    {%-   for region, default_rr in {"europe": "eu",
                                     "africa": "af",
                                     "south-america": "sa",
                                     "north-america": "na",
                                     "china-telecom": "cn-t",
                                     "china-unicom": "cn-u",
                                     "china-mobile": "cn-m",
                                     "japan": "jp",
                                     "hong-kong": "hk",
                                     "east-asia": "as",
                                     "west-asia": "eu",
                                     "oceania": "oc"}.items() %}
    {%-     do rr_dict.__setitem__(region, slave.get(region, default_rr)) %}
    {%-   endfor %}

    {#-   'code2region' maps an ISO3166 country/continent code (i.e. the client
          origin) to a geographical region. The latter is then used to find the
          right RR (thanks to 'rr_dict') #}
    {%-   for placeholder, code2region in world_split.items() %}
    {%-     for code, region in code2region.items() %}
    {%-       set origin = slave['origin'] %}
    {{ code }}.{{ placeholder }}.{{ origin }}:
      - cname: {{ disambiguate_domain_name(rr_dict[region], origin) }}
    {%-     endfor %}
    {%-   endfor %}
    {%- endfor %}

  services:
    {%- for slave in slave_instance_list %}
    {%-   set origin = slave['origin'] %}
    {{ disambiguate_domain_name(slave['record'], zone) }}:
      {#- Note: Placeholders (i.e. "country." and "continent.") are used to avoid
          possible name collisions, e.g.:
          - %cc for American Samoa is 'as'
          - %cn for Asia is also 'as' #}
      default: ['%cc.country.{{ origin }}', '%cn.continent.{{ origin }}', '{{ disambiguate_domain_name(slave['default'], origin) }}']

      # Split China's ip addresses according to ISP
      {%- for ip_range, country_code in china %}
      {{ ip_range }}: {{ country_code }}.country.{{ origin }}
      {%- endfor %}
    {%- endfor %}