Postfix3.3.1
全て データ構造 ファイル 関数 変数 型定義 マクロ定義
dnsblog.c
[詳解]
1 /*++
2 /* NAME
3 /* dnsblog 8
4 /* SUMMARY
5 /* Postfix DNS white/blacklist logger
6 /* SYNOPSIS
7 /* \fBdnsblog\fR [generic Postfix daemon options]
8 /* DESCRIPTION
9 /* The \fBdnsblog\fR(8) server implements an ad-hoc DNS
10 /* white/blacklist lookup service. This may eventually be
11 /* replaced by an UDP client that is built directly into the
12 /* \fBpostscreen\fR(8) server.
13 /* PROTOCOL
14 /* .ad
15 /* .fi
16 /* With each connection, the \fBdnsblog\fR(8) server receives
17 /* a DNS white/blacklist domain name, an IP address, and an ID.
18 /* If the IP address is listed under the DNS white/blacklist, the
19 /* \fBdnsblog\fR(8) server logs the match and replies with the
20 /* query arguments plus an address list with the resulting IP
21 /* addresses, separated by whitespace, and the reply TTL.
22 /* Otherwise it replies with the query arguments plus an empty
23 /* address list and the reply TTL; the reply TTL is -1 if there
24 /* is no reply, or a negative reply that contains no SOA record.
25 /* Finally, the \fBdnsblog\fR(8) server closes the connection.
26 /* DIAGNOSTICS
27 /* Problems and transactions are logged to \fBsyslogd\fR(8).
28 /* CONFIGURATION PARAMETERS
29 /* .ad
30 /* .fi
31 /* Changes to \fBmain.cf\fR are picked up automatically, as
32 /* \fBdnsblog\fR(8) processes run for only a limited amount
33 /* of time. Use the command "\fBpostfix reload\fR" to speed
34 /* up a change.
35 /*
36 /* The text below provides only a parameter summary. See
37 /* \fBpostconf\fR(5) for more details including examples.
38 /* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
39 /* The default location of the Postfix main.cf and master.cf
40 /* configuration files.
41 /* .IP "\fBdaemon_timeout (18000s)\fR"
42 /* How much time a Postfix daemon process may take to handle a
43 /* request before it is terminated by a built-in watchdog timer.
44 /* .IP "\fBpostscreen_dnsbl_sites (empty)\fR"
45 /* Optional list of DNS white/blacklist domains, filters and weight
46 /* factors.
47 /* .IP "\fBipc_timeout (3600s)\fR"
48 /* The time limit for sending or receiving information over an internal
49 /* communication channel.
50 /* .IP "\fBprocess_id (read-only)\fR"
51 /* The process ID of a Postfix command or daemon process.
52 /* .IP "\fBprocess_name (read-only)\fR"
53 /* The process name of a Postfix command or daemon process.
54 /* .IP "\fBqueue_directory (see 'postconf -d' output)\fR"
55 /* The location of the Postfix top-level queue directory.
56 /* .IP "\fBsyslog_facility (mail)\fR"
57 /* The syslog facility of Postfix logging.
58 /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR"
59 /* A prefix that is prepended to the process name in syslog
60 /* records, so that, for example, "smtpd" becomes "prefix/smtpd".
61 /* .PP
62 /* Available in Postfix 3.3 and later:
63 /* .IP "\fBservice_name (read-only)\fR"
64 /* The master.cf service name of a Postfix daemon process.
65 /* SEE ALSO
66 /* smtpd(8), Postfix SMTP server
67 /* postconf(5), configuration parameters
68 /* syslogd(5), system logging
69 /* LICENSE
70 /* .ad
71 /* .fi
72 /* The Secure Mailer license must be distributed with this software.
73 /* HISTORY
74 /* .ad
75 /* .fi
76 /* This service was introduced with Postfix version 2.8.
77 /* AUTHOR(S)
78 /* Wietse Venema
79 /* IBM T.J. Watson Research
80 /* P.O. Box 704
81 /* Yorktown Heights, NY 10598, USA
82 /*
83 /* Wietse Venema
84 /* Google, Inc.
85 /* 111 8th Avenue
86 /* New York, NY 10011, USA
87 /*--*/
88 
89 /* System library. */
90 
91 #include <sys_defs.h>
92 #include <limits.h>
93 
94 /* Utility library. */
95 
96 #include <msg.h>
97 #include <vstream.h>
98 #include <vstring.h>
99 #include <argv.h>
100 #include <myaddrinfo.h>
101 #include <valid_hostname.h>
102 #include <sock_addr.h>
103 
104 /* Global library. */
105 
106 #include <mail_conf.h>
107 #include <mail_version.h>
108 #include <mail_proto.h>
109 #include <mail_params.h>
110 
111 /* DNS library. */
112 
113 #include <dns.h>
114 
115 /* Server skeleton. */
116 
117 #include <mail_server.h>
118 
119 /* Application-specific. */
120 
121  /*
122  * Tunable parameters.
123  */
125 
126  /*
127  * Static so we don't allocate and free on every request.
128  */
129 static VSTRING *rbl_domain;
130 static VSTRING *addr;
131 static VSTRING *query;
132 static VSTRING *why;
133 static VSTRING *result;
134 
135  /*
136  * Silly little macros.
137  */
138 #define STR(x) vstring_str(x)
139 #define LEN(x) VSTRING_LEN(x)
140 
141 /* static void dnsblog_query - query DNSBL for client address */
142 
143 static VSTRING *dnsblog_query(VSTRING *result, int *result_ttl,
144  const char *dnsbl_domain,
145  const char *addr)
146 {
147  const char *myname = "dnsblog_query";
148  ARGV *octets;
149  int i;
150  struct addrinfo *res;
151  unsigned char *ipv6_addr;
152  int dns_status;
153  DNS_RR *addr_list;
154  DNS_RR *rr;
155  MAI_HOSTADDR_STR hostaddr;
156 
157  if (msg_verbose)
158  msg_info("%s: addr %s dnsbl_domain %s",
159  myname, addr, dnsbl_domain);
160 
161  VSTRING_RESET(query);
162 
163  /*
164  * Reverse the client IPV6 address, represented as 32 hexadecimal
165  * nibbles. We use the binary address to avoid tricky code. Asking for an
166  * AAAA record makes no sense here. Just like with IPv4 we use the lookup
167  * result as a bit mask, not as an IP address.
168  */
169 #ifdef HAS_IPV6
170  if (valid_ipv6_hostaddr(addr, DONT_GRIPE)) {
171  if (hostaddr_to_sockaddr(addr, (char *) 0, 0, &res) != 0
172  || res->ai_family != PF_INET6)
173  msg_fatal("%s: unable to convert address %s", myname, addr);
174  ipv6_addr = (unsigned char *) &SOCK_ADDR_IN6_ADDR(res->ai_addr);
175  for (i = sizeof(SOCK_ADDR_IN6_ADDR(res->ai_addr)) - 1; i >= 0; i--)
176  vstring_sprintf_append(query, "%x.%x.",
177  ipv6_addr[i] & 0xf, ipv6_addr[i] >> 4);
178  freeaddrinfo(res);
179  } else
180 #endif
181 
182  /*
183  * Reverse the client IPV4 address, represented as four decimal octet
184  * values. We use the textual address for convenience.
185  */
186  {
187  octets = argv_split(addr, ".");
188  for (i = octets->argc - 1; i >= 0; i--) {
189  vstring_strcat(query, octets->argv[i]);
190  vstring_strcat(query, ".");
191  }
192  argv_free(octets);
193  }
194 
195  /*
196  * Tack on the RBL domain name and query the DNS for an A record.
197  */
198  vstring_strcat(query, dnsbl_domain);
199  dns_status = dns_lookup_x(STR(query), T_A, 0, &addr_list, (VSTRING *) 0,
200  why, (int *) 0, DNS_REQ_FLAG_NCACHE_TTL);
201 
202  /*
203  * We return the lowest TTL in the response from the A record(s) if
204  * found, or from the SOA record(s) if available. If the reply specifies
205  * no TTL, or if the query fails, we return a TTL of -1.
206  */
207  VSTRING_RESET(result);
208  *result_ttl = -1;
209  if (dns_status == DNS_OK) {
210  for (rr = addr_list; rr != 0; rr = rr->next) {
211  if (dns_rr_to_pa(rr, &hostaddr) == 0) {
212  msg_warn("%s: skipping reply record type %s for query %s: %m",
213  myname, dns_strtype(rr->type), STR(query));
214  } else {
215  msg_info("addr %s listed by domain %s as %s",
216  addr, dnsbl_domain, hostaddr.buf);
217  if (LEN(result) > 0)
218  vstring_strcat(result, " ");
219  vstring_strcat(result, hostaddr.buf);
220  /* Grab the positive reply TTL. */
221  if (*result_ttl < 0 || *result_ttl > rr->ttl)
222  *result_ttl = rr->ttl;
223  }
224  }
225  dns_rr_free(addr_list);
226  } else if (dns_status == DNS_NOTFOUND) {
227  if (msg_verbose)
228  msg_info("%s: addr %s not listed by domain %s",
229  myname, addr, dnsbl_domain);
230  /* Grab the negative reply TTL. */
231  for (rr = addr_list; rr != 0; rr = rr->next) {
232  if (rr->type == T_SOA && (*result_ttl < 0 || *result_ttl > rr->ttl))
233  *result_ttl = rr->ttl;
234  }
235  dns_rr_free(addr_list);
236  } else {
237  msg_warn("%s: lookup error for DNS query %s: %s",
238  myname, STR(query), STR(why));
239  }
240  VSTRING_TERMINATE(result);
241  return (result);
242 }
243 
244 /* dnsblog_service - perform service for client */
245 
246 static void dnsblog_service(VSTREAM *client_stream, char *unused_service,
247  char **argv)
248 {
249  int request_id;
250  int result_ttl;
251 
252  /*
253  * Sanity check. This service takes no command-line arguments.
254  */
255  if (argv[0])
256  msg_fatal("unexpected command-line argument: %s", argv[0]);
257 
258  /*
259  * This routine runs whenever a client connects to the socket dedicated
260  * to the dnsblog service. All connection-management stuff is handled by
261  * the common code in single_server.c.
262  */
263  if (attr_scan(client_stream,
265  RECV_ATTR_STR(MAIL_ATTR_RBL_DOMAIN, rbl_domain),
267  RECV_ATTR_INT(MAIL_ATTR_LABEL, &request_id),
268  ATTR_TYPE_END) == 3) {
269  (void) dnsblog_query(result, &result_ttl, STR(rbl_domain), STR(addr));
270  if (var_dnsblog_delay > 0)
271  sleep(var_dnsblog_delay);
272  attr_print(client_stream, ATTR_FLAG_NONE,
273  SEND_ATTR_STR(MAIL_ATTR_RBL_DOMAIN, STR(rbl_domain)),
275  SEND_ATTR_INT(MAIL_ATTR_LABEL, request_id),
277  SEND_ATTR_INT(MAIL_ATTR_TTL, result_ttl),
278  ATTR_TYPE_END);
279  vstream_fflush(client_stream);
280  }
281 }
282 
283 /* post_jail_init - post-jail initialization */
284 
285 static void post_jail_init(char *unused_name, char **unused_argv)
286 {
287  rbl_domain = vstring_alloc(100);
288  addr = vstring_alloc(100);
289  query = vstring_alloc(100);
290  why = vstring_alloc(100);
291  result = vstring_alloc(100);
292  var_use_limit = 0;
293 }
294 
296 
297 /* main - pass control to the multi-threaded skeleton */
298 
299 int main(int argc, char **argv)
300 {
301  static const CONFIG_TIME_TABLE time_table[] = {
303  0,
304  };
305 
306  /*
307  * Fingerprint executables and core dumps.
308  */
310 
311  single_server_main(argc, argv, dnsblog_service,
312  CA_MAIL_SERVER_TIME_TABLE(time_table),
313  CA_MAIL_SERVER_POST_INIT(post_jail_init),
315  0);
316 }
int msg_verbose
Definition: msg.c:177
#define DNS_REQ_FLAG_NCACHE_TTL
Definition: dns.h:249
#define MAIL_ATTR_RBL_ADDR
Definition: mail_proto.h:196
const char * dns_strtype(unsigned)
Definition: dns_strtype.c:187
int valid_ipv6_hostaddr(const char *addr, int gripe)
#define ATTR_FLAG_NONE
Definition: attr.h:98
#define CA_MAIL_SERVER_UNLIMITED
Definition: mail_server.h:70
void freeaddrinfo(struct addrinfo *ai)
Definition: myaddrinfo.c:742
MAIL_VERSION_STAMP_DECLARE
Definition: dnsblog.c:295
int main(int argc, char **argv)
Definition: dnsblog.c:299
ARGV * argv_free(ARGV *argvp)
Definition: argv.c:136
Definition: argv.h:17
#define DNS_NOTFOUND
Definition: dns.h:278
char ** argv
Definition: argv.h:20
#define RECV_ATTR_INT(name, val)
Definition: attr.h:71
#define ATTR_TYPE_END
Definition: attr.h:39
#define MAIL_ATTR_ACT_CLIENT_ADDR
Definition: mail_proto.h:216
int hostaddr_to_sockaddr(const char *hostaddr, const char *service, int socktype, struct addrinfo **res)
Definition: myaddrinfo.c:464
const char * dns_rr_to_pa(DNS_RR *, MAI_HOSTADDR_STR *)
Definition: dns_rr_to_pa.c:53
#define VSTRING_TERMINATE(vp)
Definition: vstring.h:74
#define CA_MAIL_SERVER_POST_INIT(v)
Definition: mail_server.h:65
int dns_lookup_x(const char *, unsigned, unsigned, DNS_RR **, VSTRING *, VSTRING *, int *, unsigned)
Definition: dns_lookup.c:914
char buf[MAI_HOSTADDR_STRSIZE]
Definition: myaddrinfo.h:146
VSTRING * vstring_sprintf_append(VSTRING *vp, const char *format,...)
Definition: vstring.c:624
#define attr_print
Definition: attr.h:109
#define VSTRING_RESET(vp)
Definition: vstring.h:77
#define DNS_OK
Definition: dns.h:284
void msg_warn(const char *fmt,...)
Definition: msg.c:215
VSTRING * vstring_alloc(ssize_t len)
Definition: vstring.c:353
#define MAIL_ATTR_TTL
Definition: mail_proto.h:169
int var_use_limit
Definition: mail_params.c:248
#define MAIL_VERSION_STAMP_ALLOCATE
Definition: mail_version.h:67
#define MAIL_ATTR_LABEL
Definition: mail_proto.h:170
struct DNS_RR * next
Definition: dns.h:147
#define CA_MAIL_SERVER_TIME_TABLE(v)
Definition: mail_server.h:59
#define SEND_ATTR_INT(name, val)
Definition: attr.h:63
#define STR(x)
Definition: dnsblog.c:138
NORETURN msg_fatal(const char *fmt,...)
Definition: msg.c:249
int vstream_fflush(VSTREAM *stream)
Definition: vstream.c:1257
ARGV * argv_split(const char *, const char *)
Definition: argv_split.c:63
#define MAIL_ATTR_RBL_DOMAIN
Definition: mail_proto.h:191
NORETURN single_server_main(int, char **, SINGLE_SERVER_FN,...)
ssize_t argc
Definition: argv.h:19
unsigned int ttl
Definition: dns.h:144
#define VAR_DNSBLOG_DELAY
Definition: mail_params.h:3794
unsigned short type
Definition: dns.h:142
int var_dnsblog_delay
Definition: dnsblog.c:124
#define attr_scan
Definition: attr.h:111
void dns_rr_free(DNS_RR *)
Definition: dns_rr.c:137
Definition: dns.h:139
#define ATTR_FLAG_MORE
Definition: attr.h:101
#define SEND_ATTR_STR(name, val)
Definition: attr.h:64
VSTRING * vstring_strcat(VSTRING *vp, const char *src)
Definition: vstring.c:459
#define LEN(x)
Definition: dnsblog.c:139
#define DEF_DNSBLOG_DELAY
Definition: mail_params.h:3795
#define RECV_ATTR_STR(name, val)
Definition: attr.h:72
#define DONT_GRIPE
Definition: haproxy_srvr.h:31
#define ATTR_FLAG_STRICT
Definition: attr.h:103
void msg_info(const char *fmt,...)
Definition: msg.c:199