Compare commits

...

4 Commits

Author SHA1 Message Date
Vladimir Dubrovin
454f5e1d54 -Ne / -Ni description added to man
Some checks are pending
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Waiting to run
2026-04-13 21:37:46 +03:00
Vladimir Dubrovin
c4ac696919 Update documentation for parent tcps/https/etc 2026-04-13 21:32:04 +03:00
Vladimir Dubrovin
afbdad0ac7 Fix for first in chain https/tcps parent 2026-04-13 21:09:46 +03:00
Vladimir Dubrovin
a1a65c3fd5 ssl_client_mode = 3 added, allow 'secure' parent types ending with 's': https, tcps, socks5s, connect+s, etc.
example:

plugin SSLPlugin.ld.so ssl_plugin

allow user1
parent 1000 http 1.1.1.1 1111
allow user2
parent 1000 https 2.2.2.2 2222
ssl_client_mode 3
ssl_client
proxy

With ssl_client_mode 3 TLS is only handshaked for https parent type and is not handshaked for http parent.
2026-04-13 20:53:38 +03:00
10 changed files with 137 additions and 12 deletions

View File

@ -711,6 +711,29 @@ ssl_client_ca_file /etc/ssl/certs/ca-certificates.crt
ssl_cli
proxy -p3128
</pre>
<p>
<b>Conditional TLS for parent proxy (ssl_client_mode 3):</b>
<br>With ssl_client_mode 3, TLS handshake to parent proxy is performed only if the parent type ends with 's' (secure types). This allows mixing secure and non-secure parent proxies in the same configuration:
</p><pre>
plugin /path/to/SSLPlugin.ld.so ssl_plugin
ssl_server_cert /etc/3proxy/certs/server.crt
ssl_server_key /etc/3proxy/certs/server.key
ssl_client_mode 3
auth strong
allow user1
parent 1000 https parent1.example.com 443
allow user2
parent 1000 socks5 parent2.example.com 1080
ssl_serv
ssl_cli
proxy -p3128
ssl_noserv
ssl_nocli
</pre>
<p>
This creates an HTTPS proxy (ssl_serv) that accepts TLS connections from clients. For parent proxy connections, user1's traffic goes through an https parent with TLS encryption (secure type), while user2's traffic goes through a regular socks5 parent without TLS. Secure parent types include: tcps, https, connects, connect+s, socks4s, socks5s, socks4+s, socks5+s, pop3s, smtps, ftps.
</p>
<li><a name="CERTIFICATES"><i>How to create CA and certificates for SSLPlugin</i></a>
<p>
<b>Creating a Certificate Authority (CA):</b>

View File

@ -720,6 +720,29 @@ ssl_client_ca_file /etc/ssl/certs/ca-certificates.crt
ssl_cli
proxy -p3128
</pre>
<p>
<b>Условное TLS для parent прокси (ssl_client_mode 3):</b>
<br>При ssl_client_mode 3 TLS-рукопожатие с родительским прокси выполняется только если тип parent прокси заканчивается на 's' (защищённые типы). Это позволяет смешивать защищённые и незащищённые родительские прокси в одной конфигурации:
</p><pre>
plugin /path/to/SSLPlugin.ld.so ssl_plugin
ssl_server_cert /etc/3proxy/certs/server.crt
ssl_server_key /etc/3proxy/certs/server.key
ssl_client_mode 3
auth strong
allow user1
parent 1000 https parent1.example.com 443
allow user2
parent 1000 socks5 parent2.example.com 1080
ssl_serv
ssl_cli
proxy -p3128
ssl_noserv
ssl_nocli
</pre>
<p>
Создаётся HTTPS-прокси (ssl_serv), принимающий TLS-соединения от клиентов. Для соединений с родительским прокси трафик user1 идёт через https родитель с TLS-шифрованием (защищённый тип), а трафик user2 — через обычный socks5 родитель без TLS. Защищённые типы parent прокси: tcps, https, connects, connect+s, socks4s, socks5s, socks4+s, socks5+s, pop3s, smtps, ftps.
</p>
<li><a name="CERTIFICATES"><i>Как создать CA и сертификаты для SSLPlugin</i></a>
<p>
<b>Создание удостоверяющего центра (CA):</b>

View File

@ -181,10 +181,15 @@ connections to. By default, connections to any interface are
accepted. Unix domain sockets can be specified with
<i>-iunix:/path/to/socket</i> syntax. On Linux, abstract
sockets use <i>-iunix:@socketname</i> syntax. <b><br>
-N</b> (for socks) External NAT address 3proxy reports to
client for BIND and UDPASSOC By default external address is
reported. It&rsquo;s only useful in the case of IP-IP NAT
(will not work for PAT) <b><br>
-Ne</b> (for socks) External NAT address (between 3proxy and
destination server) to report to client for CONNECT and
BIND. By default external address is reported. It&rsquo;s
only useful in the case of IP-IP NAT (will not work for
PAT). <b><br>
-Ni</b> (for socks) Internal NAT address (between client and
3proxy) to report to client for UDPASSOC. By default
internal address is reported. It&rsquo;s only useful in the
case of IP-IP NAT (will not work for PAT). <b><br>
-H</b> (for all services) Expect HAProxy PROXY protocol v1
header on incoming connection. This allows the proxy to
receive real client IP address from HAProxy or other load

View File

@ -44,7 +44,7 @@ ssl_cli (or ssl_client) - establish TLS connection to upstream server for servic
<br><b>ssl_client_ca_store</b> /path/to/castore - CA store for ssl_client_verify (OpenSSL 3.0+)
<br><b>ssl_client_sni</b> hostname - SNI hostname to send to upstream server (overrides the requested hostname)
<br><b>ssl_client_alpn</b> protocol1 protocol2 ... - ALPN protocols to negotiate with upstream server (e.g., ssl_client_alpn h2 http/1.1)
<br><b>ssl_client_mode</b> mode - when to establish TLS connection: 0 - on connect (default), 1 - after authentication, 2 - before data
<br><b>ssl_client_mode</b> mode - when to establish TLS connection: 0 - on connect (default), 1 - after authentication, 2 - before data, 3 - only for secure parent types (ending with 's')
<br><b>ssl_certcache</b> /path/to/cache/ - location for the generated MITM certificates cache, optional if ssl_server_ca_file / ssl_server_ca_key are configured.
The cache may contain 3 files: 3proxy.pem - public
self-signed certificates (used if ssl_server_ca_file is not configured),
@ -89,6 +89,26 @@ proxy -p3128
</pre>
Creates an HTTP proxy that connects to upstream servers via TLS with client certificate authentication.
<h4>Conditional TLS for parent proxy (ssl_client_mode 3):</h4>
<pre>
plugin /path/to/SSLPlugin.so ssl_plugin
ssl_server_cert /path/to/server.crt
ssl_server_key /path/to/key
ssl_client_mode 3
auth strong
allow user1
parent 1000 https parent1.example.com 443
allow user2
parent 1000 socks5 parent2.example.com 1080
ssl_serv
ssl_cli
proxy -p3128
ssl_noserv
ssl_nocli
</pre>
Creates an HTTP proxy on port 3128 that uses TLS for client connections (ssl_serv). With ssl_client_mode 3, TLS handshake to parent proxy is performed only if the parent type ends with 's' (secure types). In this example, user1's traffic goes through an https parent proxy with TLS encryption, while user2's traffic goes through a regular socks5 parent without TLS. Secure parent types include: tcps, https, connects, connect+s, socks4s, socks5s, socks4+s, socks5+s, pop3s, smtps, ftps.
<h4>mTLS example (require client certificate):</h4>
<pre>
plugin /path/to/SSLPlugin.so ssl_plugin

View File

@ -44,7 +44,7 @@ ssl_cli (или ssl_client) - устанавливать TLS-соединени
<br><b>ssl_client_ca_store</b> /path/to/castore - хранилище CA-сертификатов для ssl_client_verify (OpenSSL 3.0+)
<br><b>ssl_client_sni</b> hostname - SNI-имя хоста для отправки вышестоящему серверу (переопределяет запрошенное имя хоста)
<br><b>ssl_client_alpn</b> протокол1 протокол2 ... - ALPN-протоколы для согласования с вышестоящим сервером (например, ssl_client_alpn h2 http/1.1)
<br><b>ssl_client_mode</b> режим - когда устанавливать TLS-соединение: 0 - при подключении (по умолчанию), 1 - после аутентификации, 2 - перед передачей данных
<br><b>ssl_client_mode</b> режим - когда устанавливать TLS-соединение: 0 - при подключении (по умолчанию), 1 - после аутентификации, 2 - перед передачей данных, 3 - только для защищённых типов parent прокси (заканчивающихся на 's')
<br><b>ssl_certcache</b> /path/to/cache/ - расположение кеша сгенерированных MITM-сертификатов. Кеш может содержать
файлы 3proxy.pem, 3proxy.key, server.key, которые используются как ssl_server_ca_file,
ssl_server_ca_key и ssl_server_key соответственно, если они не заданы. Если server.key не задан,
@ -86,6 +86,26 @@ proxy -p3128
</pre>
Создается HTTP-прокси, который соединяется с вышестоящими серверами через TLS с аутентификацией по клиентскому сертификату.
<h4>Условное TLS для parent прокси (ssl_client_mode 3):</h4>
<pre>
plugin /path/to/SSLPlugin.so ssl_plugin
ssl_server_cert /path/to/server.crt
ssl_server_key /path/to/key
ssl_client_mode 3
auth strong
allow user1
parent 1000 https parent1.example.com 443
allow user2
parent 1000 socks5 parent2.example.com 1080
ssl_serv
ssl_cli
proxy -p3128
ssl_noserv
ssl_nocli
</pre>
Создается HTTP-прокси на порту 3128, использующий TLS для клиентских соединений (ssl_serv). При ssl_client_mode 3 TLS-рукопожатие с родительским прокси выполняется только если тип parent прокси заканчивается на 's' (защищённые типы). В данном примере трафик user1 идёт через https родительский прокси с TLS-шифрованием, а трафик user2 — через обычный socks5 родитель без TLS. Защищённые типы parent прокси: tcps, https, connects, connect+s, socks4s, socks5s, socks4+s, socks5+s, pop3s, smtps, ftps.
<h4>Пример mTLS (требование клиентского сертификата):</h4>
<pre>
plugin /path/to/SSLPlugin.so ssl_plugin

View File

@ -193,10 +193,11 @@ syntax. On Linux, abstract sockets use
.I -iunix:@socketname
syntax.
.br
.B -N
(for socks) External NAT address 3proxy reports to client for BIND and UDPASSOC
By default external address is reported. It's only useful in the case
of IP-IP NAT (will not work for PAT)
.B -Ne
(for socks) External NAT address (between 3proxy and destination server) to report to client for CONNECT and BIND. By default external address is reported. It's only useful in the case of IP-IP NAT (will not work for PAT).
.br
.B -Ni
(for socks) Internal NAT address (between client and 3proxy) to report to client for UDPASSOC. By default internal address is reported. It's only useful in the case of IP-IP NAT (will not work for PAT).
.br
.B -H
(for all services) Expect HAProxy PROXY protocol v1 header on incoming connection.

View File

@ -8,6 +8,14 @@
#include "proxy.h"
static FILTER_ACTION (*ext_ssl_parent)(struct clientparam * param) = NULL;
static FILTER_ACTION ssl_parent(struct clientparam * param){
if(ext_ssl_parent) return ext_ssl_parent(param);
ext_ssl_parent = pluginlink.findbyname("ssl_parent");
if(ext_ssl_parent) return ext_ssl_parent(param);
return REJECT;
}
int clientnegotiate(struct chain * redir, struct clientparam * param, struct sockaddr * addr, unsigned char * hostname){
unsigned char *buf;
@ -33,6 +41,10 @@ int clientnegotiate(struct chain * redir, struct clientparam * param, struct soc
pass = param->password;
}
}
if(redir->secure){
res = ssl_parent(param);
if(res != PASS) return res;
}
switch(redir->type){
case R_TCP:
case R_HTTP:
@ -351,6 +363,7 @@ int handleredirect(struct clientparam * param, struct ace * acentry){
param->extpassword = (unsigned char *)mystrdup((char *)((*cur->extuser == '*' && param->password)?param->password : cur->extpass));
}
}
if(redir->secure) return ssl_parent(param);
return 0;
}
connected = 1;

View File

@ -795,8 +795,13 @@ static int h_parent(int argc, unsigned char **argv){
return(3);
}
for(i = 0; redirs[i].name ; i++){
if(!strcmp((char *)argv[2], redirs[i].name)) {
int len;
len = strlen(redirs[i].name);
if(!strncmp((char *)argv[2], redirs[i].name, len)
&& (argv[2][len] == 0 || (argv[2][len] == 's' && argv[2][len+1] == 0))
) {
chains->type = redirs[i].redir;
if(argv[2][len] == 's') chains->secure = 1;
break;
}
}

View File

@ -759,6 +759,14 @@ static FILTER_ACTION ssl_filter_predata(void *fc, struct clientparam * param){
return PASS;
}
static FILTER_ACTION ssl_parent(struct clientparam * param){
if(PCONF->cli && client_mode == 3) {
if(docli(param)) {
return REJECT;
}
}
return PASS;
}
static void ssl_filter_clear(void *state){
struct clientparam *param;
@ -1158,6 +1166,10 @@ static struct commands ssl_commandhandlers[] = {
{NULL, "ssl_certcache", h_certcache, 2, 2},
};
static struct symbol ssl_symbols[] = {
{NULL, "ssl_parent", (void *)&ssl_parent},
};
#ifdef WATCOM
#pragma aux ssl_plugin "*" parm caller [ ] value struct float struct routine [eax] modify [eax ecx edx]
@ -1221,6 +1233,8 @@ PLUGINAPI int PLUGINCALL ssl_plugin (struct pluginlink * pluginlink,
ssl_init();
ssl_commandhandlers[(sizeof(ssl_commandhandlers)/sizeof(struct commands))-1].next = pl->commandhandlers->next;
pl->commandhandlers->next = ssl_commandhandlers;
ssl_symbols[0].next = pl->symbols.next;
pl->symbols.next = ssl_symbols;
}
tcppmfunc = (PROXYFUNC)pl->findbyname("tcppm");

View File

@ -326,6 +326,7 @@ extern struct redirdesc redirs[];
struct chain {
struct chain * next;
int type;
int secure;
PROXYSOCKADDRTYPE addr;
unsigned char * exthost;
unsigned char * extuser;
@ -415,7 +416,7 @@ extern int numservers;
typedef void * (* PROXYFUNC)(struct clientparam *);
typedef enum {
PASS,
PASS = 0,
CONTINUE,
HANDLED,
REJECT,