]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/doh.hh
dnsdist: Add support for the processing of X-Forwarded-For headers
[thirdparty/pdns.git] / pdns / doh.hh
1 /*
2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * In addition, for the avoidance of any doubt, permission is granted to
10 * link this program with OpenSSL and to (re)distribute the binaries
11 * produced as the result of such linking.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22 #pragma once
23 #include "iputils.hh"
24 #include "libssl.hh"
25
26 struct DOHServerConfig;
27
28 class DOHResponseMapEntry
29 {
30 public:
31 DOHResponseMapEntry(const std::string& regex, uint16_t status, const std::string& content, const boost::optional<std::vector<std::pair<std::string, std::string>>>& headers): d_regex(regex), d_customHeaders(headers), d_content(content), d_status(status)
32 {
33 }
34
35 bool matches(const std::string& path) const
36 {
37 return d_regex.match(path);
38 }
39
40 uint16_t getStatusCode() const
41 {
42 return d_status;
43 }
44
45 const std::string& getContent() const
46 {
47 return d_content;
48 }
49
50 const boost::optional<std::vector<std::pair<std::string, std::string>>>& getHeaders() const
51 {
52 return d_customHeaders;
53 }
54
55 private:
56 Regex d_regex;
57 boost::optional<std::vector<std::pair<std::string, std::string>>> d_customHeaders;
58 std::string d_content;
59 uint16_t d_status;
60 };
61
62 struct DOHFrontend
63 {
64 DOHFrontend()
65 {
66 }
67
68 std::shared_ptr<DOHServerConfig> d_dsc{nullptr};
69 std::vector<std::shared_ptr<DOHResponseMapEntry>> d_responsesMap;
70 TLSConfig d_tlsConfig;
71 TLSErrorCounters d_tlsCounters;
72 std::string d_serverTokens{"h2o/dnsdist"};
73 std::vector<std::pair<std::string, std::string>> d_customResponseHeaders;
74 ComboAddress d_local;
75
76 uint32_t d_idleTimeout{30}; // HTTP idle timeout in seconds
77 std::vector<std::string> d_urls;
78
79 std::atomic<uint64_t> d_httpconnects{0}; // number of TCP/IP connections established
80 std::atomic<uint64_t> d_getqueries{0}; // valid DNS queries received via GET
81 std::atomic<uint64_t> d_postqueries{0}; // valid DNS queries received via POST
82 std::atomic<uint64_t> d_badrequests{0}; // request could not be converted to dns query
83 std::atomic<uint64_t> d_errorresponses{0}; // dnsdist set 'error' on response
84 std::atomic<uint64_t> d_redirectresponses{0}; // dnsdist set 'redirect' on response
85 std::atomic<uint64_t> d_validresponses{0}; // valid responses sent out
86
87 struct HTTPVersionStats
88 {
89 std::atomic<uint64_t> d_nbQueries{0}; // valid DNS queries received
90 std::atomic<uint64_t> d_nb200Responses{0};
91 std::atomic<uint64_t> d_nb400Responses{0};
92 std::atomic<uint64_t> d_nb403Responses{0};
93 std::atomic<uint64_t> d_nb500Responses{0};
94 std::atomic<uint64_t> d_nb502Responses{0};
95 std::atomic<uint64_t> d_nbOtherResponses{0};
96 };
97
98 HTTPVersionStats d_http1Stats;
99 HTTPVersionStats d_http2Stats;
100 bool d_sendCacheControlHeaders{true};
101 bool d_trustForwardedForHeader{false};
102
103 time_t getTicketsKeyRotationDelay() const
104 {
105 return d_tlsConfig.d_ticketsKeyRotationDelay;
106 }
107
108 #ifndef HAVE_DNS_OVER_HTTPS
109 void setup()
110 {
111 }
112
113 void reloadCertificates()
114 {
115 }
116
117 void rotateTicketsKey(time_t now)
118 {
119 }
120
121 void loadTicketsKeys(const std::string& keyFile)
122 {
123 }
124
125 void handleTicketsKeyRotation()
126 {
127 }
128
129 time_t getNextTicketsKeyRotation() const
130 {
131 return 0;
132 }
133
134 size_t getTicketsKeysCount() const
135 {
136 size_t res = 0;
137 return res;
138 }
139
140 #else
141 void setup();
142 void reloadCertificates();
143
144 void rotateTicketsKey(time_t now);
145 void loadTicketsKeys(const std::string& keyFile);
146 void handleTicketsKeyRotation();
147 time_t getNextTicketsKeyRotation() const;
148 size_t getTicketsKeysCount() const;
149 #endif /* HAVE_DNS_OVER_HTTPS */
150 };
151
152 #ifndef HAVE_DNS_OVER_HTTPS
153 struct DOHUnit
154 {
155 };
156
157 #else /* HAVE_DNS_OVER_HTTPS */
158 #include <unordered_map>
159
160 struct st_h2o_req_t;
161
162 struct DOHUnit
163 {
164 DOHUnit()
165 {
166 }
167 DOHUnit(const DOHUnit&) = delete;
168 DOHUnit& operator=(const DOHUnit&) = delete;
169
170 void get()
171 {
172 ++d_refcnt;
173 }
174
175 void release()
176 {
177 if (--d_refcnt == 0) {
178 delete this;
179 }
180 }
181
182 std::string query;
183 std::string response;
184 ComboAddress remote;
185 ComboAddress dest;
186 st_h2o_req_t* req{nullptr};
187 DOHUnit** self{nullptr};
188 std::string contentType;
189 std::atomic<uint64_t> d_refcnt{1};
190 int rsock;
191 uint16_t qtype;
192 /* the status_code is set from
193 processDOHQuery() (which is executed in
194 the DOH client thread) so that the correct
195 response can be sent in on_dnsdist(),
196 after the DOHUnit has been passed back to
197 the main DoH thread.
198 */
199 uint16_t status_code{200};
200 bool ednsAdded{false};
201
202 std::string getHTTPPath() const;
203 std::string getHTTPHost() const;
204 std::string getHTTPScheme() const;
205 std::string getHTTPQueryString() const;
206 std::unordered_map<std::string, std::string> getHTTPHeaders() const;
207 void setHTTPResponse(uint16_t statusCode, const std::string& body, const std::string& contentType="");
208 };
209
210 #endif /* HAVE_DNS_OVER_HTTPS */
211
212 void handleDOHTimeout(DOHUnit* oldDU);