Also make the proxy_* variables meaningful for events associated with proxied transports.
&$proxy_target_address$& &&&
&$proxy_target_port$& &&&
&$proxy_session$&
-These variables are only available when built with Proxy Protocol support
+These variables are only available when built with Proxy Protocol
+or Socks5 support
For details see chapter &<<SECTproxyInbound>>&.
.wen
&` queue_time_overall `& time on queue for whole message
&` pid `& Exim process id
.new
-&` proxy `& proxy address on <= lines
+&` proxy `& proxy address on <= and => lines
.wen
&` received_recipients `& recipients on <= lines
&` received_sender `& sender on <= lines
.cindex "TCP/IP" "logging proxy address"
&%proxy%&: The internal (closest to the system running Exim) IP address
of the proxy, tagged by PRX=, on the &"<="& line for a message accepted
-on a proxied connection.
+on a proxied connection
+or the &"=>"& line for a message delivered on a proxied connection..
See &<<SECTproxyInbound>>& for more information.
.wen
.next
main configuration option to a hostlist; connections from these
hosts will use Proxy Protocol.
-To log the IP of the proxy in the incoming logline, add &"+proxy"&
-to the &%log_selector%& option.
-This will add a component tagged with &"PRX="& to the line.
-
The following expansion variables are usable
(&"internal"& and &"external"& here refer to the interfaces
of the proxy):
Proxies from the list are tried according to their priority
and weight settings until one responds. The timeout for the
overall connection applies to the set of proxied attempts.
+
+.section Logging SECTproxyLog
+To log the (local) IP of a proxy in the incoming or delivery logline,
+add &"+proxy"& to the &%log_selector%& option.
+This will add a component tagged with &"PRX="& to the line.
.wen
. ////////////////////////////////////////////////////////////////////////////
JH/26 Move PROXY support from Experimental to mainline, enabled for a build
by defining SUPPORT_PROXY. Note that the proxy_required_hosts option
- is renamed to hosts_proxy.
+ is renamed to hosts_proxy, and the proxy_{host,target}_{address,port}.
+ variables are renamed to proxy_{local,external}_{address,port}.
Exim version 4.86
if (LOGGING(outgoing_port))
s = string_append(s, sizep, ptrp, 2, US":", string_sprintf("%d",
addr->host_used->port));
+
+#ifdef SUPPORT_SOCKS
+if (LOGGING(proxy) && proxy_local_address)
+ {
+ s = string_append(s, sizep, ptrp, 3, US" PRX=[", proxy_local_address, US"]");
+ if (LOGGING(outgoing_port))
+ s = string_append(s, sizep, ptrp, 2, US":", string_sprintf("%d",
+ proxy_local_port));
+ }
+#endif
+
return d_log_interface(s, sizep, ptrp);
}
+
+
#ifdef SUPPORT_TLS
static uschar *
d_tlslog(uschar * s, int * sizep, int * ptrp, address_item * addr)
switch (subid)
{
+#ifdef SUPPORT_SOCKS
+ case '2': /* proxy information; must arrive before A0 and applies to that addr XXX oops*/
+ proxy_session = TRUE; /*XXX shouod this be cleared somewhere? */
+ if (*ptr == 0)
+ ptr++;
+ else
+ {
+ proxy_local_address = string_copy(ptr);
+ while(*ptr++);
+ memcpy(&proxy_local_port, ptr, sizeof(proxy_local_port));
+ ptr += sizeof(proxy_local_port);
+ }
+ break;
+#endif
+
#ifdef EXPERIMENTAL_DSN_INFO
case '1': /* must arrive before A0, and applies to that addr */
/* Two strings: smtp_greeting and helo_response */
#ifdef SUPPORT_TLS
if (addr->cipher)
{
- ptr = big_buffer;
- sprintf(CS ptr, "%.128s", addr->cipher);
- while(*ptr++);
+ ptr = big_buffer + sprintf(CS big_buffer, "%.128s", addr->cipher) + 1;
if (!addr->peerdn)
*ptr++ = 0;
else
{
- sprintf(CS ptr, "%.512s", addr->peerdn);
- while(*ptr++);
+ ptr += sprintf(CS ptr, "%.512s", addr->peerdn);
+ ptr++;
}
rmt_dlv_checked_write(fd, 'X', '1', big_buffer, ptr - big_buffer);
# ifndef DISABLE_OCSP
if (addr->ocsp > OCSP_NOT_REQ)
{
- ptr = big_buffer;
- sprintf(CS ptr, "%c", addr->ocsp + '0');
- while(*ptr++);
+ ptr = big_buffer + sprintf(CS big_buffer, "%c", addr->ocsp + '0') + 1;
rmt_dlv_checked_write(fd, 'X', '4', big_buffer, ptr - big_buffer);
}
# endif
if (client_authenticator)
{
- ptr = big_buffer;
- sprintf(CS big_buffer, "%.64s", client_authenticator);
- while(*ptr++);
+ ptr = big_buffer + sprintf(CS big_buffer, "%.64s", client_authenticator) + 1;
rmt_dlv_checked_write(fd, 'C', '1', big_buffer, ptr - big_buffer);
}
if (client_authenticated_id)
{
- ptr = big_buffer;
- sprintf(CS big_buffer, "%.64s", client_authenticated_id);
- while(*ptr++);
+ ptr = big_buffer + sprintf(CS big_buffer, "%.64s", client_authenticated_id) + 1;
rmt_dlv_checked_write(fd, 'C', '2', big_buffer, ptr - big_buffer);
}
if (client_authenticated_sender)
{
- ptr = big_buffer;
- sprintf(CS big_buffer, "%.64s", client_authenticated_sender);
- while(*ptr++);
+ ptr = big_buffer + sprintf(CS big_buffer, "%.64s", client_authenticated_sender) + 1;
rmt_dlv_checked_write(fd, 'C', '3', big_buffer, ptr - big_buffer);
}
rmt_dlv_checked_write(fd, 'R', '0', big_buffer, ptr - big_buffer);
}
+#ifdef SUPPORT_SOCKS
+ if (LOGGING(proxy) && proxy_session)
+ {
+ ptr = big_buffer;
+ if (proxy_local_address)
+ {
+ DEBUG(D_deliver) debug_printf("proxy_local_address '%s'\n", proxy_local_address);
+ ptr = big_buffer + sprintf(CS ptr, "%.128s", proxy_local_address) + 1;
+ DEBUG(D_deliver) debug_printf("proxy_local_port %d\n", proxy_local_port);
+ memcpy(ptr, &proxy_local_port, sizeof(proxy_local_port));
+ ptr += sizeof(proxy_local_port);
+ }
+ else
+ *ptr++ = '\0';
+ rmt_dlv_checked_write(fd, 'A', '2', big_buffer, ptr - big_buffer);
+ }
+#endif
+
#ifdef EXPERIMENTAL_DSN_INFO
/*um, are they really per-addr? Other per-conn stuff is not (auth, tls). But host_used is! */
if (addr->smtp_greeting)
{
- ptr = big_buffer;
DEBUG(D_deliver) debug_printf("smtp_greeting '%s'\n", addr->smtp_greeting);
- sprintf(CS ptr, "%.128s", addr->smtp_greeting);
- while(*ptr++);
+ ptr = big_buffer + sprintf(CS big_buffer, "%.128s", addr->smtp_greeting) + 1;
if (addr->helo_response)
{
DEBUG(D_deliver) debug_printf("helo_response '%s'\n", addr->helo_response);
- sprintf(CS ptr, "%.128s", addr->helo_response);
- while(*ptr++);
+ ptr += sprintf(CS ptr, "%.128s", addr->helo_response) + 1;
}
else
*ptr++ = '\0';
/* The rest of the information goes in an 'A0' item. */
- sprintf(CS big_buffer, "%c%c", addr->transport_return,
- addr->special_action);
+ sprintf(CS big_buffer, "%c%c", addr->transport_return, addr->special_action);
ptr = big_buffer + 2;
memcpy(ptr, &(addr->basic_errno), sizeof(addr->basic_errno));
ptr += sizeof(addr->basic_errno);
ptr += sizeof(addr->flags);
if (!addr->message) *ptr++ = 0; else
- {
- sprintf(CS ptr, "%.1024s", addr->message);
- while(*ptr++);
- }
+ ptr += sprintf(CS ptr, "%.1024s", addr->message) + 1;
if (!addr->user_message) *ptr++ = 0; else
- {
- sprintf(CS ptr, "%.1024s", addr->user_message);
- while(*ptr++);
- }
+ ptr += sprintf(CS ptr, "%.1024s", addr->user_message) + 1;
if (!addr->host_used) *ptr++ = 0; else
{
- sprintf(CS ptr, "%.256s", addr->host_used->name);
- while(*ptr++);
- sprintf(CS ptr, "%.64s", addr->host_used->address);
- while(*ptr++);
+ ptr += sprintf(CS ptr, "%.256s", addr->host_used->name) + 1;
+ ptr += sprintf(CS ptr, "%.64s", addr->host_used->address) + 1;
memcpy(ptr, &(addr->host_used->port), sizeof(addr->host_used->port));
ptr += sizeof(addr->host_used->port);
if (LOGGING(incoming_interface) && sending_ip_address)
#endif
{
- uschar * ptr = big_buffer;
- sprintf(CS ptr, "%.128s", sending_ip_address);
- while(*ptr++);
- sprintf(CS ptr, "%d", sending_port);
- while(*ptr++);
-
+ uschar * ptr;
+ ptr = big_buffer + sprintf(CS big_buffer, "%.128s", sending_ip_address) + 1;
+ ptr += sprintf(CS ptr, "%d", sending_port) + 1;
rmt_dlv_checked_write(fd, 'I', '0', big_buffer, ptr - big_buffer);
}
{ "prdr_requested", vtype_bool, &prdr_requested },
#endif
{ "primary_hostname", vtype_stringptr, &primary_hostname },
-#ifdef SUPPORT_PROXY
- { "proxy_host_address", vtype_stringptr, &proxy_host_address },
- { "proxy_host_port", vtype_int, &proxy_host_port },
+#if defined(SUPPORT_PROXY) || defined(SUPPORT_SOCKS)
+ { "proxy_external_address",vtype_stringptr, &proxy_external_address },
+ { "proxy_external_port", vtype_int, &proxy_external_port },
+ { "proxy_local_address", vtype_stringptr, &proxy_local_address },
+ { "proxy_local_port", vtype_int, &proxy_local_port },
{ "proxy_session", vtype_bool, &proxy_session },
- { "proxy_target_address",vtype_stringptr, &proxy_target_address },
- { "proxy_target_port", vtype_int, &proxy_target_port },
#endif
{ "prvscheck_address", vtype_stringptr, &prvscheck_address },
{ "prvscheck_keynum", vtype_stringptr, &prvscheck_keynum },
BIT_TABLE(L, outgoing_interface),
BIT_TABLE(L, outgoing_port),
BIT_TABLE(L, pid),
-#ifdef SUPPORT_PROXY
+#if defined(SUPPORT_PROXY) || defined (SUPPORT_SOCKS)
BIT_TABLE(L, proxy),
#endif
BIT_TABLE(L, queue_run),
uschar *process_log_path = NULL;
BOOL prod_requires_admin = TRUE;
-#ifdef SUPPORT_PROXY
+#if defined(SUPPORT_PROXY) || defined(SUPPORT_SOCKS)
uschar *hosts_proxy = US"";
-uschar *proxy_host_address = US"";
-int proxy_host_port = 0;
+uschar *proxy_external_address = US"";
+int proxy_external_port = 0;
+uschar *proxy_local_address = US"";
+int proxy_local_port = 0;
BOOL proxy_session = FALSE;
BOOL proxy_session_failed = FALSE;
-uschar *proxy_target_address = US"";
-int proxy_target_port = 0;
#endif
uschar *prvscheck_address = NULL;
extern uschar *process_log_path; /* Alternate path */
extern BOOL prod_requires_admin; /* TRUE if prodding requires admin */
-#ifdef SUPPORT_PROXY
+#if defined(SUPPORT_PROXY) || defined(SUPPORT_SOCKS)
extern uschar *hosts_proxy; /* Hostlist which (require) use proxy protocol */
-extern uschar *proxy_host_address; /* IP of host being proxied */
-extern int proxy_host_port; /* Port of host being proxied */
+extern uschar *proxy_external_address; /* IP of remote interface of proxy */
+extern int proxy_external_port; /* Port on remote interface of proxy */
+extern uschar *proxy_local_address; /* IP of local interface of proxy */
+extern int proxy_local_port; /* Port on local interface of proxy */
extern BOOL proxy_session; /* TRUE if receiving mail from valid proxy */
extern BOOL proxy_session_failed; /* TRUE if required proxy negotiation failed */
-extern uschar *proxy_target_address; /* IP of proxy server inbound */
-extern int proxy_target_port; /* Port of proxy server inbound */
#endif
extern uschar *prvscheck_address; /* Set during prvscheck expansion item */
#ifdef SUPPORT_PROXY
if (proxy_session && LOGGING(proxy))
- s = string_append(s, &size, &sptr, 2, US" PRX=", proxy_host_address);
+ s = string_append(s, &size, &sptr, 2, US" PRX=", proxy_local_address);
#endif
sprintf(CS big_buffer, "%d", msg_size);
DEBUG(D_receive) debug_printf("Invalid %s source IP\n", iptype);
return ERRNO_PROXYFAIL;
}
- proxy_host_address = sender_host_address;
+ proxy_local_address = sender_host_address;
sender_host_address = string_copy(US tmpip);
tmpport = ntohs(hdr.v2.addr.ip4.src_port);
- proxy_host_port = sender_host_port;
+ proxy_local_port = sender_host_port;
sender_host_port = tmpport;
/* Save dest ip/port */
tmpaddr.sin_addr.s_addr = hdr.v2.addr.ip4.dst_addr;
DEBUG(D_receive) debug_printf("Invalid %s source IP\n", iptype);
return ERRNO_PROXYFAIL;
}
- proxy_host_address = sender_host_address;
+ proxy_local_address = sender_host_address;
sender_host_address = string_copy(US tmpip6);
tmpport = ntohs(hdr.v2.addr.ip6.src_port);
- proxy_host_port = sender_host_port;
+ proxy_local_port = sender_host_port;
sender_host_port = tmpport;
/* Save dest ip/port */
memmove(tmpaddr6.sin6_addr.s6_addr, hdr.v2.addr.ip6.dst_addr, 16);
debug_printf("Proxied src arg is not an %s address\n", iptype);
goto proxyfail;
}
- proxy_host_address = sender_host_address;
+ proxy_local_address = sender_host_address;
sender_host_address = p;
p = sp + 1;
if ((sp = Ustrchr(p, ' ')) == NULL)
debug_printf("Proxied src port '%s' not an integer\n", p);
goto proxyfail;
}
- proxy_host_port = sender_host_port;
+ proxy_local_port = sender_host_port;
sender_host_port = tmp_port;
p = sp + 1;
if ((sp = Ustrchr(p, '\0')) == NULL)
if ((fd = smtp_sock_connect(&proxy, proxy_af, sob->port,
interface, tb, sob->timeout)) >= 0)
+ {
+ proxy_local_address = string_copy(proxy.address);
+ proxy_local_port = sob->port;
break;
+ }
log_write(0, LOG_MAIN, "%s: %s", __FUNCTION__, strerror(errno));
sob->is_failed = TRUE;
)
goto proxy_err;
-/*XXX log proxy outbound addr/port? */
+proxy_external_address = string_copy(
+ host_ntoa(buf[3] == 4 ? AF_INET6 : AF_INET, buf+4, NULL, NULL));
+proxy_external_port = ntohs(*((uint16_t *)(buf + (buf[3] == 4 ? 20 : 8))));
+proxy_session = TRUE;
+
HDEBUG(D_transport|D_acl|D_v)
- debug_printf(" proxy farside local: [%s]:%d\n",
- host_ntoa(buf[3] == 4 ? AF_INET6 : AF_INET, buf+4, NULL, NULL),
- ntohs(*((uint16_t *)(buf + (buf[3] == 4 ? 20 : 8)))));
+ debug_printf(" proxy farside: [%s]:%d\n", proxy_external_address, proxy_external_port);
return fd;
# ----- Main settings -----
+log_selector = +proxy +outgoing_port
+
domainlist local_domains = test.ex : *.test.ex
acl_smtp_rcpt = accept
driver = smtp
interface = HOSTIPV4
port = PORT_S
- socks_proxy = 127.0.0.1 port=PORT_S OPT
+ socks_proxy = 127.0.0.1 port=PORT_D OPT
debug_print = transport_name <$transport_name>
1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss
-1999-03-02 09:44:33 10HmaX-0005vi-00 => userx@test.ex R=my_main_router T=my_smtp H=127.0.0.1 [127.0.0.1] C="250 accepted OK"
+1999-03-02 09:44:33 10HmaX-0005vi-00 => userx@test.ex R=my_main_router T=my_smtp H=127.0.0.1 [127.0.0.1]:1224 PRX=[127.0.0.1]:1225 C="250 accepted OK"
1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss
-1999-03-02 09:44:33 10HmaY-0005vi-00 => userx@test.ex R=my_main_router T=my_smtp H=127.0.0.1 [127.0.0.1] C="250 accepted OK"
+1999-03-02 09:44:33 10HmaY-0005vi-00 => userx@test.ex R=my_main_router T=my_smtp H=127.0.0.1 [127.0.0.1]:1224 PRX=[127.0.0.1]:1225 C="250 accepted OK"
1999-03-02 09:44:33 10HmaY-0005vi-00 Completed
munge loopback
#
# auth: null
-server PORT_S
+server PORT_D
<<\x05\x01\x00
>>\x05\x00
<<\x05\x01\x00\x01\x7f\x00\x00\x01\x04\xc8
#
#
# auth: username/password
-server PORT_S
+server PORT_D
<<\x05\x01\x02
>>\x05\x02
<<\x01\x04fred\x05fubar
221 myhost.test.ex closing connection\r
******** SERVER ********
-Listening on port 1224 ...
+Listening on port 1225 ...
Connection request from [ip4.ip4.ip4.ip4]
<<\x05\x01\x00
>>\x05\x00
QUIT
250 bye
End of script
-Listening on port 1224 ...
+Listening on port 1225 ...
Connection request from [ip4.ip4.ip4.ip4]
<<\x05\x01\x02
>>\x05\x02