* `SpoofAction(ip[, ip])` or `SpoofAction({ip, ip, ..}): forge a response with the specified IPv4 (for an A query) or IPv6 (for an AAAA). If you specify multiple addresses, all that match the query type (A, AAAA or ANY) will get spoofed in
* `SpoofCNAMEAction(cname)`: forge a response with the specified CNAME value
* `TCAction()`: create answer to query with TC and RD bits set, to move to TCP/IP
- * `TeeAction(remote)`: send copy of query to remote, keep stats on responses
+ * `TeeAction(remote[, addECS])`: send copy of query to remote, keep stats on responses. If `addECS` is set to `true`, EDNS Client Subnet information will be added to the query
* Specialist rule generators
* `addAnyTCRule()`: generate TC=1 answers to ANY queries received over UDP, moving them to TCP
* `addDomainSpoof(domain, ip[, ip6])` or `addDomainSpoof(domain, {IP, IP, IP..})`: generate answers for A/AAAA/ANY queries using the ip parameters
return std::make_shared<RemoteLogger>(ComboAddress(remote), timeout ? *timeout : 2, maxQueuedEntries ? *maxQueuedEntries : 100, reconnectWaitTime ? *reconnectWaitTime : 1);
});
- g_lua.writeFunction("TeeAction", [](const std::string& remote) {
- setLuaNoSideEffect();
- return std::shared_ptr<DNSAction>(new TeeAction(ComboAddress(remote, 53)));
+ g_lua.writeFunction("TeeAction", [](const std::string& remote, boost::optional<bool> addECS) {
+ return std::shared_ptr<DNSAction>(new TeeAction(ComboAddress(remote, 53), addECS ? *addECS : false));
});
g_lua.registerFunction<void(DNSAction::*)()>("printStats", [](const DNSAction& ta) {
using namespace std;
-TeeAction::TeeAction(const ComboAddress& ca) : d_remote(ca)
+TeeAction::TeeAction(const ComboAddress& ca, bool addECS) : d_remote(ca), d_addECS(addECS)
{
d_fd=SSocket(d_remote.sin4.sin_family, SOCK_DGRAM, 0);
SConnect(d_fd, d_remote);
if(dq->tcp)
d_tcpdrops++;
else {
+ ssize_t res;
d_queries++;
- if(send(d_fd, (char*)dq->dh, dq->len, 0) <= 0)
+
+ if(d_addECS) {
+ std::string query;
+ std::string larger;
+ uint16_t len = dq->len;
+ bool ednsAdded = false;
+ bool ecsAdded = false;
+ query.reserve(dq->size);
+ query.assign((char*) dq->dh, len);
+
+ handleEDNSClientSubnet((char*) query.c_str(), query.size(), dq->qname->wirelength(), &len, larger, &ednsAdded, &ecsAdded, *dq->remote);
+
+ if (larger.empty()) {
+ res = send(d_fd, query.c_str(), len, 0);
+ }
+ else {
+ res = send(d_fd, larger.c_str(), larger.length(), 0);
+ }
+ }
+ else {
+ res = send(d_fd, (char*)dq->dh, dq->len, 0);
+ }
+
+ if (res <= 0)
d_senderrors++;
}
return DNSAction::Action::None;
class TeeAction : public DNSAction
{
public:
- TeeAction(const ComboAddress& ca);
+ TeeAction(const ComboAddress& ca, bool addECS=false);
~TeeAction();
DNSAction::Action operator()(DNSQuestion* dq, string* ruleresult) const override;
string toString() const override;
mutable unsigned long d_tcpdrops{0};
unsigned long d_otherrcode{0};
std::atomic<bool> d_pleaseQuit{false};
+ bool d_addECS{false};
};