dosev 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dosev/__init__.py +6 -0
- dosev/cli.py +81 -0
- dosev/config.py +295 -0
- dosev/resolver.py +2448 -0
- dosev/server.py +704 -0
- dosev/utils.py +46 -0
- dosev-1.0.0.dist-info/METADATA +145 -0
- dosev-1.0.0.dist-info/RECORD +12 -0
- dosev-1.0.0.dist-info/WHEEL +5 -0
- dosev-1.0.0.dist-info/entry_points.txt +2 -0
- dosev-1.0.0.dist-info/licenses/LICENSE +21 -0
- dosev-1.0.0.dist-info/top_level.txt +1 -0
dosev/__init__.py
ADDED
dosev/cli.py
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
import argparse
|
|
4
|
+
from .config import load_config, _default_log_dir
|
|
5
|
+
from .server import run_server_sync
|
|
6
|
+
|
|
7
|
+
def main() -> None:
|
|
8
|
+
parser = argparse.ArgumentParser(description="dosev DNS server")
|
|
9
|
+
parser.add_argument("--config", "-c", default="config/dosev.conf",
|
|
10
|
+
help="Path to configuration file (default: config/dosev.conf)")
|
|
11
|
+
parser.add_argument("--check-config", action="store_true",
|
|
12
|
+
help="Validate the configuration and exit without starting the server")
|
|
13
|
+
args = parser.parse_args()
|
|
14
|
+
|
|
15
|
+
try:
|
|
16
|
+
config = load_config(args.config)
|
|
17
|
+
except Exception as e:
|
|
18
|
+
print(f"Failed to load config: {e}", file=sys.stderr)
|
|
19
|
+
sys.exit(1)
|
|
20
|
+
|
|
21
|
+
if args.check_config:
|
|
22
|
+
print("Configuration is valid.")
|
|
23
|
+
return
|
|
24
|
+
|
|
25
|
+
run_server_sync(
|
|
26
|
+
listen_ip=config["listen_ip"],
|
|
27
|
+
listen_port=config["listen_port"],
|
|
28
|
+
upstream_dns=config["upstream_dns"],
|
|
29
|
+
protocol=config["protocol"],
|
|
30
|
+
verbose=config.get("verbose", False),
|
|
31
|
+
blocklists=config.get("blocklists"),
|
|
32
|
+
disable_ipv6=config.get("disable_ipv6", False),
|
|
33
|
+
dns_cache_ttl=config.get("dns_cache_ttl", 300),
|
|
34
|
+
dns_cache_max_size=config.get("dns_cache_max_size", 1024),
|
|
35
|
+
dns_negative_cache_ttl=config.get("dns_negative_cache_ttl", 5),
|
|
36
|
+
dns_logging_enabled=config.get("dns_logging_enabled", False),
|
|
37
|
+
dns_log_retention_days=config.get("dns_log_retention_days", 7),
|
|
38
|
+
dns_log_dir=config.get("dns_log_dir", _default_log_dir()),
|
|
39
|
+
dns_log_prefix=config.get("dns_log_prefix", "dns-log"),
|
|
40
|
+
dns_pinned_certs=config.get("dns_pinned_certs", {}),
|
|
41
|
+
dnssec_enabled=config.get("dnssec_enabled", False),
|
|
42
|
+
auto_update_trust_anchor=config.get("auto_update_trust_anchor", True), # NEW
|
|
43
|
+
trust_anchors_file=config.get("trust_anchors_file", ""),
|
|
44
|
+
metrics_enabled=config.get("metrics_enabled", False),
|
|
45
|
+
metrics_port=config.get("metrics_port", 8000),
|
|
46
|
+
uvloop_enable=config.get("uvloop_enable", False),
|
|
47
|
+
upstream_retries=config.get("upstream_retries", 2),
|
|
48
|
+
upstream_udp_timeout=config.get("upstream_udp_timeout", 2.0),
|
|
49
|
+
upstream_tcp_timeout=config.get("upstream_tcp_timeout", 5.0),
|
|
50
|
+
upstream_doh_timeout=config.get("upstream_doh_timeout", 5.0),
|
|
51
|
+
rate_limit_rps=config.get("rate_limit_rps", 0.0),
|
|
52
|
+
rate_limit_burst=config.get("rate_limit_burst", 0.0),
|
|
53
|
+
upstreams=config.get("upstreams", []),
|
|
54
|
+
optimistic_cache_enabled=config.get("optimistic_cache_enabled", False),
|
|
55
|
+
optimistic_stale_max_age=config.get("optimistic_stale_max_age", 86400),
|
|
56
|
+
optimistic_stale_response_ttl=config.get("optimistic_stale_response_ttl", 30),
|
|
57
|
+
dns_privilege_drop_user=config.get("dns_privilege_drop_user", ""),
|
|
58
|
+
dns_privilege_drop_group=config.get("dns_privilege_drop_group", ""),
|
|
59
|
+
dns_chroot_dir=config.get("dns_chroot_dir", ""),
|
|
60
|
+
dns_rebind_protection=config.get("dns_rebind_protection", False),
|
|
61
|
+
dns_rebind_action=config.get("dns_rebind_action", "strip"),
|
|
62
|
+
dns_ecs_enabled=config.get("dns_ecs_enabled", True),
|
|
63
|
+
dns_max_payload=config.get("dns_max_payload", 4096),
|
|
64
|
+
dns_enable_dot=config.get("dns_enable_dot", False),
|
|
65
|
+
dns_dot_port=config.get("dns_dot_port", 853),
|
|
66
|
+
dns_dot_cert_file=config.get("dns_dot_cert_file", ""),
|
|
67
|
+
dns_dot_key_file=config.get("dns_dot_key_file", ""),
|
|
68
|
+
dns_enable_doh=config.get("dns_enable_doh", False),
|
|
69
|
+
dns_doh_port=config.get("dns_doh_port", 443),
|
|
70
|
+
dns_doh_cert_file=config.get("dns_doh_cert_file", ""),
|
|
71
|
+
dns_doh_key_file=config.get("dns_doh_key_file", ""),
|
|
72
|
+
dns_doh_path=config.get("dns_doh_path", "/dns-query"),
|
|
73
|
+
pool_max_size=config.get("pool_max_size", 5),
|
|
74
|
+
pool_idle_timeout=config.get("pool_idle_timeout", 60.0),
|
|
75
|
+
doh_version=config.get("doh_version", "auto"),
|
|
76
|
+
doh_auto_cache_ttl=config.get("doh_auto_cache_ttl", 3600),
|
|
77
|
+
bootstrap=config.get("bootstrap", {"servers": [], "timeout": 2.0, "retries": 2}),
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
if __name__ == "__main__":
|
|
81
|
+
main()
|
dosev/config.py
ADDED
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import configparser
|
|
3
|
+
import warnings
|
|
4
|
+
from typing import Dict, Any, List, Optional
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def _default_log_dir() -> str:
|
|
8
|
+
if os.name == 'nt':
|
|
9
|
+
return os.path.join(os.getenv('LOCALAPPDATA') or os.path.expanduser('~'), 'dosev', 'logs')
|
|
10
|
+
return '/var/log/dosev'
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _validate_and_warn(config: Dict[str, Any]) -> None:
|
|
14
|
+
listen_port = config.get('listen_port', 53)
|
|
15
|
+
if not isinstance(listen_port, int) or not 1 <= listen_port <= 65535:
|
|
16
|
+
raise ValueError('listen_port must be between 1 and 65535')
|
|
17
|
+
|
|
18
|
+
dns_max_payload = config.get('dns_max_payload', 4096)
|
|
19
|
+
if not isinstance(dns_max_payload, int) or not 512 <= dns_max_payload <= 4096:
|
|
20
|
+
raise ValueError('dns_max_payload must be between 512 and 4096')
|
|
21
|
+
|
|
22
|
+
protocol = config.get('protocol', 'udp')
|
|
23
|
+
if protocol not in {'udp', 'tcp', 'tls', 'https', 'quic'}:
|
|
24
|
+
raise ValueError('protocol must be one of: udp, tcp, tls, https, quic')
|
|
25
|
+
|
|
26
|
+
if config.get('dns_enable_dot', False) and not (config.get('dns_dot_cert_file') and config.get('dns_dot_key_file')):
|
|
27
|
+
raise ValueError('dns_enable_dot requires dns_dot_cert_file and dns_dot_key_file')
|
|
28
|
+
|
|
29
|
+
if config.get('dns_enable_doh', False) and not (config.get('dns_doh_cert_file') and config.get('dns_doh_key_file')):
|
|
30
|
+
raise ValueError('dns_enable_doh requires dns_doh_cert_file and dns_doh_key_file')
|
|
31
|
+
|
|
32
|
+
if config.get('dns_enable_dot', False) or config.get('dns_enable_doh', False):
|
|
33
|
+
if config.get('protocol') == 'udp':
|
|
34
|
+
warnings.warn('Secure listeners are enabled while the main resolver protocol is udp; this is usually intentional but verify your upstream defaults.', RuntimeWarning)
|
|
35
|
+
|
|
36
|
+
rate_limit_rps = config.get('rate_limit_rps', 0.0)
|
|
37
|
+
if rate_limit_rps < 0:
|
|
38
|
+
raise ValueError('rate_limit_rps must be non-negative')
|
|
39
|
+
|
|
40
|
+
rate_limit_burst = config.get('rate_limit_burst', 0.0)
|
|
41
|
+
if rate_limit_burst < 0:
|
|
42
|
+
raise ValueError('rate_limit_burst must be non-negative')
|
|
43
|
+
|
|
44
|
+
if config.get('metrics_enabled', False) and config.get('metrics_port', 8000) == 53:
|
|
45
|
+
warnings.warn('Metrics are enabled on port 53; this may conflict with DNS traffic.', RuntimeWarning)
|
|
46
|
+
|
|
47
|
+
if config.get('doh_version', 'auto') not in {'auto', '1.1', '2', '3'}:
|
|
48
|
+
raise ValueError('doh_version must be auto, 1.1, 2, or 3')
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def load_config(path: str = 'config/dosev.conf') -> Dict[str, Any]:
|
|
52
|
+
config = configparser.ConfigParser()
|
|
53
|
+
if not os.path.exists(path):
|
|
54
|
+
return {
|
|
55
|
+
'listen_ip': '0.0.0.0',
|
|
56
|
+
'listen_port': 53,
|
|
57
|
+
'upstream_dns': '1.1.1.1',
|
|
58
|
+
'protocol': 'udp',
|
|
59
|
+
'verbose': False,
|
|
60
|
+
'disable_ipv6': False,
|
|
61
|
+
'strip_ipv6_records': None, # None = use disable_ipv6 value
|
|
62
|
+
'dns_cache_ttl': 300,
|
|
63
|
+
'dns_cache_max_size': 1024,
|
|
64
|
+
'dns_negative_cache_ttl': 5,
|
|
65
|
+
'dns_logging_enabled': False,
|
|
66
|
+
'dns_log_retention_days': 7,
|
|
67
|
+
'dns_log_dir': _default_log_dir(),
|
|
68
|
+
'dns_log_prefix': 'dns-log',
|
|
69
|
+
'dns_pinned_certs': {},
|
|
70
|
+
'dns_ecs_enabled': True,
|
|
71
|
+
'dnssec_enabled': False,
|
|
72
|
+
'auto_update_trust_anchor': True,
|
|
73
|
+
'trust_anchors_file': '',
|
|
74
|
+
'metrics_enabled': False,
|
|
75
|
+
'metrics_port': 8000,
|
|
76
|
+
'uvloop_enable': False,
|
|
77
|
+
'upstream_retries': 2,
|
|
78
|
+
'upstream_udp_timeout': 2.0,
|
|
79
|
+
'upstream_tcp_timeout': 5.0,
|
|
80
|
+
'upstream_doh_timeout': 5.0,
|
|
81
|
+
'rate_limit_rps': 0.0,
|
|
82
|
+
'rate_limit_burst': 0.0,
|
|
83
|
+
'upstreams': [],
|
|
84
|
+
'optimistic_cache_enabled': False,
|
|
85
|
+
'optimistic_stale_max_age': 86400,
|
|
86
|
+
'optimistic_stale_response_ttl': 30,
|
|
87
|
+
'dns_privilege_drop_user': '',
|
|
88
|
+
'dns_privilege_drop_group': '',
|
|
89
|
+
'dns_chroot_dir': '',
|
|
90
|
+
'dns_rebind_protection': False,
|
|
91
|
+
'dns_rebind_action': 'strip',
|
|
92
|
+
'pool_max_size': 5,
|
|
93
|
+
'pool_idle_timeout': 60.0,
|
|
94
|
+
'doh_version': 'auto',
|
|
95
|
+
'doh_auto_cache_ttl': 3600,
|
|
96
|
+
'bootstrap': {'servers': ['1.1.1.1:53', '8.8.8.8:53'], 'timeout': 2.0, 'retries': 2},
|
|
97
|
+
'blocklists': {
|
|
98
|
+
'enabled': False,
|
|
99
|
+
'urls': [],
|
|
100
|
+
'interval_seconds': 86400,
|
|
101
|
+
'action': 'NXDOMAIN',
|
|
102
|
+
'local_blocklist_dir': 'blocklists',
|
|
103
|
+
'reload_on_change': True,
|
|
104
|
+
},
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
config.read(path)
|
|
108
|
+
|
|
109
|
+
listen_ip = config.get('server', 'listen_ip', fallback='0.0.0.0')
|
|
110
|
+
listen_port = config.getint('server', 'listen_port', fallback=53)
|
|
111
|
+
|
|
112
|
+
upstream_dns = config.get('resolver', 'upstream_dns', fallback='1.1.1.1')
|
|
113
|
+
protocol = config.get('resolver', 'protocol', fallback='udp').lower()
|
|
114
|
+
verbose = config.getboolean('resolver', 'verbose', fallback=False)
|
|
115
|
+
disable_ipv6 = config.getboolean('resolver', 'disable_ipv6', fallback=False)
|
|
116
|
+
dns_ecs_enabled = config.getboolean('resolver', 'dns_ecs_enabled', fallback=True)
|
|
117
|
+
dns_max_payload = config.getint('resolver', 'dns_max_payload', fallback=4096)
|
|
118
|
+
dns_enable_dot = config.getboolean('resolver', 'dns_enable_dot', fallback=False)
|
|
119
|
+
dns_dot_port = config.getint('resolver', 'dns_dot_port', fallback=853)
|
|
120
|
+
dns_dot_cert_file = config.get('resolver', 'dns_dot_cert_file', fallback='')
|
|
121
|
+
dns_dot_key_file = config.get('resolver', 'dns_dot_key_file', fallback='')
|
|
122
|
+
dns_enable_doh = config.getboolean('resolver', 'dns_enable_doh', fallback=False)
|
|
123
|
+
dns_doh_port = config.getint('resolver', 'dns_doh_port', fallback=443)
|
|
124
|
+
dns_doh_cert_file = config.get('resolver', 'dns_doh_cert_file', fallback='')
|
|
125
|
+
dns_doh_key_file = config.get('resolver', 'dns_doh_key_file', fallback='')
|
|
126
|
+
dns_doh_path = config.get('resolver', 'dns_doh_path', fallback='/dns-query')
|
|
127
|
+
strip_ipv6_records_raw = config.get('resolver', 'strip_ipv6_records', fallback=None)
|
|
128
|
+
if strip_ipv6_records_raw is None:
|
|
129
|
+
strip_ipv6_records = None
|
|
130
|
+
else:
|
|
131
|
+
strip_ipv6_records = config.getboolean('resolver', 'strip_ipv6_records', fallback=None)
|
|
132
|
+
|
|
133
|
+
dns_cache_ttl = config.getint('cache', 'ttl', fallback=300)
|
|
134
|
+
dns_cache_max_size = config.getint('cache', 'max_size', fallback=1024)
|
|
135
|
+
dns_negative_cache_ttl = config.getint('cache', 'negative_ttl', fallback=5)
|
|
136
|
+
|
|
137
|
+
upstream_udp_timeout = config.getfloat('timeouts', 'udp', fallback=2.0)
|
|
138
|
+
upstream_tcp_timeout = config.getfloat('timeouts', 'tcp', fallback=5.0)
|
|
139
|
+
upstream_doh_timeout = config.getfloat('timeouts', 'doh', fallback=5.0)
|
|
140
|
+
|
|
141
|
+
upstream_retries = config.getint('advanced', 'retries', fallback=2)
|
|
142
|
+
rate_limit_rps = config.getfloat('advanced', 'rate_limit_rps', fallback=0.0)
|
|
143
|
+
rate_limit_burst = config.getfloat('advanced', 'rate_limit_burst', fallback=0.0)
|
|
144
|
+
optimistic_cache_enabled = config.getboolean('advanced', 'optimistic_cache_enabled', fallback=False)
|
|
145
|
+
optimistic_stale_max_age = config.getint('advanced', 'optimistic_stale_max_age', fallback=86400)
|
|
146
|
+
optimistic_stale_response_ttl = config.getint('advanced', 'optimistic_stale_response_ttl', fallback=30)
|
|
147
|
+
pool_max_size = config.getint('advanced', 'pool_max_size', fallback=5)
|
|
148
|
+
pool_idle_timeout = config.getfloat('advanced', 'pool_idle_timeout', fallback=60.0)
|
|
149
|
+
doh_version = config.get('advanced', 'doh_version', fallback='auto').lower()
|
|
150
|
+
if doh_version not in ('auto', '1.1', '2', '3'):
|
|
151
|
+
doh_version = 'auto'
|
|
152
|
+
doh_auto_cache_ttl = config.getint('advanced', 'doh_auto_cache_ttl', fallback=3600)
|
|
153
|
+
|
|
154
|
+
dnssec_enabled = config.getboolean('security', 'dnssec_enabled', fallback=False)
|
|
155
|
+
auto_update_trust_anchor = config.getboolean('security', 'auto_update_trust_anchor', fallback=True)
|
|
156
|
+
trust_anchors_file = config.get('security', 'trust_anchors_file', fallback='')
|
|
157
|
+
|
|
158
|
+
pinned_raw = config.get('security', 'pinned_certs', fallback='')
|
|
159
|
+
dns_pinned_certs = {}
|
|
160
|
+
for item in [s.strip() for s in pinned_raw.split(',') if s.strip()]:
|
|
161
|
+
if '=' in item:
|
|
162
|
+
host, fp = item.split('=', 1)
|
|
163
|
+
dns_pinned_certs[host.strip()] = fp.strip()
|
|
164
|
+
|
|
165
|
+
dns_rebind_protection = config.getboolean('security', 'rebind_protection', fallback=False)
|
|
166
|
+
dns_rebind_action = config.get('security', 'rebind_action', fallback='strip').lower()
|
|
167
|
+
if dns_rebind_action not in ('strip', 'block'):
|
|
168
|
+
dns_rebind_action = 'strip'
|
|
169
|
+
|
|
170
|
+
dns_privilege_drop_user = config.get('security', 'dns_privilege_drop_user', fallback='')
|
|
171
|
+
dns_privilege_drop_group = config.get('security', 'dns_privilege_drop_group', fallback='')
|
|
172
|
+
dns_chroot_dir = config.get('security', 'dns_chroot_dir', fallback='')
|
|
173
|
+
|
|
174
|
+
dns_logging_enabled = config.getboolean('logging', 'enabled', fallback=False)
|
|
175
|
+
dns_log_dir = config.get('logging', 'log_dir', fallback=_default_log_dir())
|
|
176
|
+
dns_log_retention_days = config.getint('logging', 'retention_days', fallback=7)
|
|
177
|
+
dns_log_prefix = config.get('logging', 'log_prefix', fallback='dns-log')
|
|
178
|
+
|
|
179
|
+
metrics_enabled = config.getboolean('metrics', 'enabled', fallback=False)
|
|
180
|
+
metrics_port = config.getint('metrics', 'port', fallback=8000)
|
|
181
|
+
uvloop_enable = config.getboolean('metrics', 'uvloop_enable', fallback=False)
|
|
182
|
+
|
|
183
|
+
bootstrap_servers_raw = config.get('bootstrap', 'servers', fallback='')
|
|
184
|
+
if bootstrap_servers_raw.strip():
|
|
185
|
+
bootstrap_servers = [s.strip() for s in bootstrap_servers_raw.split(',') if s.strip()]
|
|
186
|
+
else:
|
|
187
|
+
bootstrap_servers = ['1.1.1.1:53', '8.8.8.8:53']
|
|
188
|
+
bootstrap_timeout = config.getfloat('bootstrap', 'timeout', fallback=2.0)
|
|
189
|
+
bootstrap_retries = config.getint('bootstrap', 'retries', fallback=2)
|
|
190
|
+
bootstrap = {
|
|
191
|
+
'servers': bootstrap_servers,
|
|
192
|
+
'timeout': bootstrap_timeout,
|
|
193
|
+
'retries': bootstrap_retries,
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
upstreams = []
|
|
197
|
+
if config.has_section('upstreams') and config.has_option('upstreams', 'servers'):
|
|
198
|
+
server_names = [s.strip() for s in config.get('upstreams', 'servers').split(',') if s.strip()]
|
|
199
|
+
for name in server_names:
|
|
200
|
+
section = f'upstreams.{name}'
|
|
201
|
+
if not config.has_section(section):
|
|
202
|
+
continue
|
|
203
|
+
address = config.get(section, 'address', fallback='')
|
|
204
|
+
if not address:
|
|
205
|
+
continue
|
|
206
|
+
proto = config.get(section, 'protocol', fallback='udp').lower()
|
|
207
|
+
port_str = config.get(section, 'port', fallback=None)
|
|
208
|
+
if port_str:
|
|
209
|
+
try:
|
|
210
|
+
port = int(port_str)
|
|
211
|
+
except ValueError:
|
|
212
|
+
port = None
|
|
213
|
+
else:
|
|
214
|
+
default_ports = {'tls': 853, 'https': 443, 'quic': 853, 'udp': 53, 'tcp': 53}
|
|
215
|
+
port = default_ports.get(proto, 53)
|
|
216
|
+
hostname = config.get(section, 'hostname', fallback='') or address
|
|
217
|
+
path = config.get(section, 'path', fallback='')
|
|
218
|
+
us_doh_version = config.get(section, 'doh_version', fallback=doh_version).lower()
|
|
219
|
+
if us_doh_version not in ('auto', '1.1', '2', '3'):
|
|
220
|
+
us_doh_version = doh_version
|
|
221
|
+
upstreams.append({
|
|
222
|
+
'address': address,
|
|
223
|
+
'protocol': proto,
|
|
224
|
+
'port': port,
|
|
225
|
+
'hostname': hostname,
|
|
226
|
+
'doh_version': us_doh_version,
|
|
227
|
+
'path': path,
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
blocklists = {
|
|
231
|
+
'enabled': config.getboolean('blocklists', 'enabled', fallback=False),
|
|
232
|
+
'urls': [u.strip() for u in config.get('blocklists', 'urls', fallback='').split(',') if u.strip()],
|
|
233
|
+
'interval_seconds': config.getint('blocklists', 'interval_seconds', fallback=86400),
|
|
234
|
+
'action': config.get('blocklists', 'action', fallback='NXDOMAIN').upper(),
|
|
235
|
+
'local_blocklist_dir': config.get('blocklists', 'local_blocklist_dir', fallback='blocklists'),
|
|
236
|
+
'reload_on_change': config.getboolean('blocklists', 'reload_on_change', fallback=True),
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
validated_config = {
|
|
240
|
+
'listen_ip': listen_ip,
|
|
241
|
+
'listen_port': listen_port,
|
|
242
|
+
'upstream_dns': upstream_dns,
|
|
243
|
+
'protocol': protocol,
|
|
244
|
+
'dns_enable_dot': dns_enable_dot,
|
|
245
|
+
'dns_dot_port': dns_dot_port,
|
|
246
|
+
'dns_dot_cert_file': dns_dot_cert_file,
|
|
247
|
+
'dns_dot_key_file': dns_dot_key_file,
|
|
248
|
+
'dns_enable_doh': dns_enable_doh,
|
|
249
|
+
'dns_doh_port': dns_doh_port,
|
|
250
|
+
'dns_doh_cert_file': dns_doh_cert_file,
|
|
251
|
+
'dns_doh_key_file': dns_doh_key_file,
|
|
252
|
+
'dns_doh_path': dns_doh_path,
|
|
253
|
+
'verbose': verbose,
|
|
254
|
+
'disable_ipv6': disable_ipv6,
|
|
255
|
+
'strip_ipv6_records': strip_ipv6_records,
|
|
256
|
+
'dns_cache_ttl': dns_cache_ttl,
|
|
257
|
+
'dns_cache_max_size': dns_cache_max_size,
|
|
258
|
+
'dns_negative_cache_ttl': dns_negative_cache_ttl,
|
|
259
|
+
'dns_logging_enabled': dns_logging_enabled,
|
|
260
|
+
'dns_log_retention_days': dns_log_retention_days,
|
|
261
|
+
'dns_log_dir': dns_log_dir,
|
|
262
|
+
'dns_log_prefix': dns_log_prefix,
|
|
263
|
+
'dns_pinned_certs': dns_pinned_certs,
|
|
264
|
+
'dns_ecs_enabled': dns_ecs_enabled,
|
|
265
|
+
'dns_max_payload': dns_max_payload,
|
|
266
|
+
'dnssec_enabled': dnssec_enabled,
|
|
267
|
+
'auto_update_trust_anchor': auto_update_trust_anchor,
|
|
268
|
+
'metrics_enabled': metrics_enabled,
|
|
269
|
+
'metrics_port': metrics_port,
|
|
270
|
+
'uvloop_enable': uvloop_enable,
|
|
271
|
+
'upstream_retries': upstream_retries,
|
|
272
|
+
'upstream_udp_timeout': upstream_udp_timeout,
|
|
273
|
+
'upstream_tcp_timeout': upstream_tcp_timeout,
|
|
274
|
+
'upstream_doh_timeout': upstream_doh_timeout,
|
|
275
|
+
'rate_limit_rps': rate_limit_rps,
|
|
276
|
+
'rate_limit_burst': rate_limit_burst,
|
|
277
|
+
'upstreams': upstreams,
|
|
278
|
+
'optimistic_cache_enabled': optimistic_cache_enabled,
|
|
279
|
+
'optimistic_stale_max_age': optimistic_stale_max_age,
|
|
280
|
+
'optimistic_stale_response_ttl': optimistic_stale_response_ttl,
|
|
281
|
+
'dns_privilege_drop_user': dns_privilege_drop_user,
|
|
282
|
+
'dns_privilege_drop_group': dns_privilege_drop_group,
|
|
283
|
+
'dns_chroot_dir': dns_chroot_dir,
|
|
284
|
+
'dns_rebind_protection': dns_rebind_protection,
|
|
285
|
+
'dns_rebind_action': dns_rebind_action,
|
|
286
|
+
'pool_max_size': pool_max_size,
|
|
287
|
+
'pool_idle_timeout': pool_idle_timeout,
|
|
288
|
+
'doh_version': doh_version,
|
|
289
|
+
'doh_auto_cache_ttl': doh_auto_cache_ttl,
|
|
290
|
+
'bootstrap': bootstrap,
|
|
291
|
+
'blocklists': blocklists,
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
_validate_and_warn(validated_config)
|
|
295
|
+
return validated_config
|