This is a rough design for the postscreen policy callout. Wietse
High-level description ====================== After checking the postscreen_access_list, postscreen will call out to an optional policy service before making DNS queries or sending the PREGREET banner to the client. The policy test is just another test that the client must pass before it can talk to a real Postfix SMTP server. Just like all other postscreen tests, a successful policy test is remembered for some amount of time so that a good client does not have to be tested with every connection that it makes. Configuration parameters: postscreen_policy_service = inet:host:port | unix:pathname postscreen_policy_timeout = time in seconds postscreen_policy_default_ttl = time in seconds postscreen_policy_default_action = pass | ignore | enforce | drop The host and port may be numeric or symbolic. If the policy server is local, specify 127.0.0.1 or ::1 for maximal robustness. Actions: pass: Skip this test for this client, for the amount of time specified with postscreen_policy_default_ttl. ignore, enforce, drop: These actions have the exact same meaning as with other postscreen tests (specifically, "enforce" allows other tests to complete, rejects attempts to deliver mail with a 550 SMTP reply, and logs the helo/sender/recipient information). The postscreen_policy_default_ttl value is ignored. Protocol ======== postscreen sends a request over a policy service connection and expects a reply over that same connection. Once the reply is received, that connection may be reused for another policy request. It is an error for a policy server to close a connection after sending a response. postscreen will use parallel connections when multiple policy queries are in progress. Each policy request contains name=value attributes with the local and remote address and port. Request format: client_address "=" <IPv4 address> | <IPv6 address> <newline> server_address "=" <IPv4 address> | <IPv6 address> <newline> client_port "=" <numerical port> <newline> server_port "=" <numerical port> <newline> <newline> The order of the attributes is unspecified; the order shown above is just an example for readability. A policy server must ignore attribute names that it does not know. Each policy response must contain an action and may contain a ttl value that indicates how long postscreen will skip a policy test that returns a "pass" result. Reply format: action "=" "pass" | "ignore" | "enforce" | "drop" <newline> ttl "=" <time in seconds> <newline> <newline> See "Configuration parameters" above for a description of actions. With actions other than "pass", postscreen ignores the ttl attribute. If a "pass" action specifies no ttl, postscreen_policy_default_ttl is used instead. Error handling ============== When postscreen cannot complete a policy service request, it will use the postscreen_policy_default_action and postscreen_policy_default_ttl. Examples of errors: - The policy server connection is not ready to write (write would block). - The policy server does not respond to a connection request or policy request within the postscreen_policy_timeout. - The policy server response is malformed. Alternatives considered ======================= Instead of doing the policy check before DNSBL and PREGREET checks, they could be done in parallel, at least some of the time. Then, the policy timeouts could be more relaxed. Unfortunately that requires that the PREGREET or DNSBL checks expire at the same time as the policy check ttl, which is hard to guarantee.