static_hints: StaticHintsSchema = StaticHintsSchema()
views: Optional[Dict[str, ViewSchema]] = None
policy: Optional[Dict[str, PolicySchema]] = None
- rpz: Optional[Dict[DomainName, RPZSchema]] = None
+ rpz: Optional[Dict[str, RPZSchema]] = None
stub_zones: Optional[Dict[DomainName, StubZoneSchema]] = None
forward_zones: Optional[Dict[DomainName, ForwardZoneSchema]] = None
cache: CacheSchema = CacheSchema()
static_hints: StaticHintsSchema
views: Optional[Dict[str, ViewSchema]]
policy: Optional[Dict[str, PolicySchema]]
- rpz: Optional[Dict[DomainName, RPZSchema]]
+ rpz: Optional[Dict[str, RPZSchema]]
stub_zones: Optional[Dict[DomainName, StubZoneSchema]]
forward_zones: Optional[Dict[DomainName, ForwardZoneSchema]]
cache: CacheSchema
return obj.dns64
def render_lua(self) -> Text:
- return _MAIN_TEMPLATE.render(cfg=self)
+ lua = _MAIN_TEMPLATE.render(cfg=self)
+ print(lua)
+ return lua
action: ActionEnum
file: AnyPath
watch: bool = True
- message: Optional[str] = None
- views: Optional[str] = None
+ views: Optional[List[str]] = None
options: Optional[List[FlagsEnum]] = None
+ message: Optional[str] = None
-- VIEWS section
{% include "views.lua.j2" %}
+-- RPZ section
+{% include "rpz.lua.j2" %}
+
-- STUB-ZONES section
{% include "stub_zones.lua.j2" %}
--- /dev/null
+{# Return string or table of strings #}
+{% macro string_table(table) -%}
+{%- if table is string -%}
+'{{ table|string }}'
+{%- else-%}
+{
+{%- for item in table -%}
+'{{ item|string }}',
+{%- endfor -%}
+}
+{%- endif -%}
+{%- endmacro %}
+
+{# Return str2ip or table of str2ip #}
+{% macro str2ip_table(table) -%}
+{%- if table is string -%}
+kres.str2ip('{{ table|string }}')
+{%- else-%}
+{
+{%- for item in table -%}
+kres.str2ip('{{ item|string }}'),
+{%- endfor -%}
+}
+{%- endif -%}
+{%- endmacro %}
+
+{# Return server address or table of server addresses #}
+{% macro servers_table(servers) -%}
+{%- if servers is string -%}
+'{{ servers|string }}'
+{%- else-%}
+{
+{%- for item in servers -%}
+{%- if item.address -%}
+'{{ item.address|string }}',
+{%- else -%}
+'{{ item|string }}',
+{%- endif -%}
+{%- endfor -%}
+}
+{%- endif -%}
+{%- endmacro %}
+
+{# Return server address or table of server addresses #}
+{% macro tls_servers_table(servers) -%}
+{%- if servers is string -%}
+'{{ servers|string }}', {{ tls_server_auth(servers) }}
+{%- else-%}
+{
+{%- for item in servers -%}
+{%- if item.address -%}
+{'{{ item.address|string }}', {{ tls_server_auth(item) }} },
+{%- else -%}
+'{{ item|string }}',
+{%- endif -%}
+{%- endfor -%}
+}
+{%- endif -%}
+{%- endmacro %}
+
+{% macro tls_server_auth(server) -%}
+{%- if server.hostname -%}
+hostname='{{ server.hostname|string }}',
+{%- endif -%}
+{%- if server.ca_file -%}
+ca_file='{{ server.ca_file|string }}',
+{%- endif -%}
+{%- if server.pin_sha256 -%}
+pin_sha256=
+{%- if server.pin_sha256 is string -%}
+'{{ server.pin_sha256|string }}',
+{%- else -%}
+{
+{%- for pin in server.pin_sha256 -%}
+'{{ pin|string }}',
+{%- endfor -%}
+},
+{%- endif -%}
+{%- endif -%}
+{%- endmacro %}
\ No newline at end of file
-{% macro policy_add(rule) -%}
+{% from 'macros/common_macros.lua.j2' import string_table, str2ip_table, servers_table, tls_servers_table %}
+
+{% macro policy_add(rule, postrule=false) -%}
+{%- if postrule -%}
+policy.add({{ rule }}, true)
+{% else %}
policy.add({{ rule }})
+{% endif %}
{%- endmacro %}
+{# Flags #}
{% macro policy_flags(flags) -%}
policy.FLAGS({
-{%- for flag in flags -%}
+{%- for flag in flags|list -%}
'{{ flag.upper().replace("-", "_") }}',
{%- endfor -%}
})
{%- endmacro %}
+{# Filters #}
+
+{% macro policy_all(action) -%}
+policy.all({{ action }})
+{%- endmacro %}
{% macro policy_suffix(action, suffix_table) -%}
policy.suffix({{ action }}, {{ suffix_table }})
{%- endmacro %}
+{% macro policy_pattern(action, pattern) -%}
+policy.pattern({{ action }}, {{ pattern }})
+{%- endmacro %}
-{% macro policy_stub(servers) -%}
-policy.STUB({
-{%- if servers is string %}
-'{{ addresses|string }}'
-{%- else -%}
-{%- for server in servers -%}
-{%- if server.address %}
-'{{ server.address|string }}',
-{%- else -%}
-'{{ server|string }}',
-{%- endif -%}
-{%- endfor -%}
-{%- endif -%}
-})
+{% macro policy_rpz(action, path, watch) -%}
+policy.rpz({{ action|string }}, '{{ path|string }}', {{ 'true' if watch else 'false' }})
{%- endmacro %}
+{# Non-chain actions #}
-{% macro policy_forward(servers) -%}
-policy.FORWARD({
-{%- if servers is string %}
-'{{ addresses|string }}'
-{%- else -%}
-{%- for server in servers -%}
-{%- if server.address %}
-'{{ server.address|string }}',
-{%- else -%}
-'{{ server|string }}',
-{%- endif -%}
-{%- endfor -%}
-{%- endif -%}
-})
+{% macro policy_pass() -%}
+policy.PASS
{%- endmacro %}
+{% macro policy_deny() -%}
+policy.DENY
+{%- endmacro %}
+
+{% macro policy_deny_msg(message) -%}
+policy.DENY_MSG('{{ message|string }}')
+{%- endmacro %}
+
+{% macro policy_drop() -%}
+policy.DROP
+{%- endmacro %}
-{% macro tls_auth(server) -%}
-{%- if server.hostname -%}
-hostname='{{ server.hostname|string }}',
+{% macro policy_refuse() -%}
+policy.REFUSE
+{%- endmacro %}
+
+{% macro policy_answer(answer) -%}
+policy.ANSWER({ [kres.type.{{ answer.query_type }}] = { rdata=
+{%- if answer.query_type == 'A' -%}
+{{ string_table(answer.rdata) }},
+{%- elif answer.query_type == 'AAAA' -%}
+{{ string_table(answer.rdata) }},
+{%- elif answer.query_type == 'TXT' -%}
+{{ str2ip_table(answer.rdata) }},
+{# TODO: do same for other types #}
{%- endif -%}
-{%- if server.ca_file -%}
-ca_file='{{ server.ca_file|string }}',
+{% if answer.ttl %}
+ttl={{ answer.ttl.seconds()|int }},
{%- endif -%}
-{%- if server.pin_sha256 -%}
-pin_sha256=
-{%- if server.pin_sha256 is string -%}
-'{{ server.pin_sha256|string }}',
+} }, nodata={{ 'true' if answer.nodata else 'false' }} )
+{%- endmacro %}
+
+{% macro policy_action(policy) -%}
+{%- if policy.action == 'pass' -%}
+{{ policy_pass()|string }}
+{%- elif policy.action == 'deny' -%}
+{%- if policy.message -%}
+{{ policy_deny_msg(policy.message)|string }}
{%- else -%}
-{
-{%- for pin in server.pin_sha256 -%}
-'{{ pin|string }}',
-{%- endfor -%}
-},
+{{ policy_deny()|string }}
{%- endif -%}
+{# TODO: do same for other actions #}
{%- endif -%}
{%- endmacro %}
+{# Chain actions #}
+
+{% macro policy_stub(servers) -%}
+policy.STUB({{ servers_table(servers) }})
+{%- endmacro %}
+
+{% macro policy_forward(servers) -%}
+policy.FORWARD({{ servers_table(servers) }})
+{%- endmacro %}
{% macro policy_tls_forward(servers) -%}
-policy.TLS_FORWARD({
-{%- for server in servers -%}
-{'{{ server.address }}', {{ tls_auth(server) }} },
-{%- endfor -%}
-})
+policy.TLS_FORWARD({{ tls_servers_table(servers) }})
{%- endmacro %}
+{# other #}
{% macro policy_todname(names) -%}
policy.todnames({
--- /dev/null
+{% from 'macros/policy_macros.lua.j2' import policy_flags, policy_add, policy_rpz, policy_action %}
+{% from 'macros/view_macros.lua.j2' import view_tsig, view_addr %}
+
+{% if cfg.rpz %}
+{% for id, rpz in cfg.rpz.items() %}
+-- rpz: {{ id }}
+{% if rpz.views -%}
+{# views set for rpz #}
+{% for view_id in rpz.views -%}
+{%- set view = cfg.views[view_id] -%}
+
+{# merge options from view and rpz #}
+{%- set options = none -%}
+{% if rpz.options and view.options -%}
+{% set options = rpz.options|list + view.options|list %}
+{% elif rpz.options %}
+{% set options = rpz.options|list %}
+{% elif view.options %}
+{% set options = view.options|list %}
+{%- endif %}
+
+{% if view.tsig -%}
+{% for tsig in view.tsig -%}
+
+{%- if options -%}
+{{ view_tsig(tsig|string,policy_rpz(policy_flags(rpz.options), rpz.file, rpz.watch)) }}
+{%- endif %}
+
+{{ view_tsig(tsig|string,policy_rpz(policy_action(rpz), rpz.file, rpz.watch )) }}
+
+{% endfor %}
+{%- endif -%}
+
+{% if view.subnets -%}
+{% for addr in view.subnets -%}
+
+{%- if options -%}
+{{ view_addr(addr|string,policy_rpz(policy_flags(rpz.options), rpz.file, rpz.watch)) }}
+{%- endif %}
+
+{{ view_addr(addr|string,policy_rpz(policy_action(rpz), rpz.file, rpz.watch )) }}
+
+{% endfor %}
+{% endif %}
+
+{% endfor %}
+{% else %}
+{# no views set for rpz #}
+
+{% if rpz.options -%}
+{{ policy_add(policy_rpz(policy_flags(rpz.options), rpz.file, rpz.watch)) }}
+{%- endif %}
+
+{{ policy_add(policy_rpz(policy_action(rpz), rpz.file, rpz.watch )) }}
+
+{% endif %}
+{% endfor %}
+{% endif %}
\ No newline at end of file