Compare commits

...

4 Commits

Author SHA1 Message Date
Vladimir Dubrovin
305f9932ac Update docs
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
C/C++ CI cmake / ubuntu-latest (wolfSSL) (push) Waiting to run
2026-07-22 18:47:11 +03:00
Vladimir Dubrovin
c94766dff7 Fix: dnspr was broken since udppm rewrite. -F (fake resolve to redirect traffic) option added to dnspr 2026-07-22 17:34:51 +03:00
Vladimir Dubrovin
87fc8ae4ee Fix cmake build 2026-07-22 16:23:11 +03:00
Vladimir Dubrovin
9ab2e820b5 Added imapp, starttls support for smtpp, pop3p, tlspr 2026-07-22 16:15:50 +03:00
36 changed files with 1458 additions and 159 deletions

3
.gitignore vendored
View File

@ -18,6 +18,7 @@ bin/socks
bin/tcppm
bin/udppm
bin/pop3p
bin/imapp
bin/smtpp
bin/ftppr
bin/mycrypt
@ -45,6 +46,7 @@ src/socks
src/tcppm
src/udppm
src/pop3p
src/imapp
src/smtpp
src/ftppr
src/icqpr
@ -261,6 +263,7 @@ CLAUDE.md
bin/3proxy_crypt
bin/3proxy_ftppr
bin/3proxy_pop3p
bin/3proxy_imapp
bin/3proxy_proxy
bin/3proxy_smtpp
bin/3proxy_socks

View File

@ -70,6 +70,7 @@ option(3PROXY_BUILD_NONE "Do not build standalone binaries" OFF)
option(3PROXY_BUILD_PROXY "Build standalone proxy binary" ON)
option(3PROXY_BUILD_SOCKS "Build standalone socks binary" ON)
option(3PROXY_BUILD_POP3P "Build standalone pop3p binary" ON)
option(3PROXY_BUILD_IMAPP "Build standalone imapp binary" ON)
option(3PROXY_BUILD_SMTPP "Build standalone smtpp binary" ON)
option(3PROXY_BUILD_FTPPR "Build standalone ftppr binary" ON)
option(3PROXY_BUILD_TCPPM "Build standalone tcppm binary" ON)
@ -77,7 +78,7 @@ option(3PROXY_BUILD_UDPPM "Build standalone udppm binary" ON)
option(3PROXY_BUILD_TLSPR "Build standalone tlspr binary" ON)
if(3PROXY_BUILD_NONE)
foreach(_M PROXY SOCKS POP3P SMTPP FTPPR TCPPM UDPPM TLSPR)
foreach(_M PROXY SOCKS POP3P IMAPP SMTPP FTPPR TCPPM UDPPM TLSPR)
set(3PROXY_BUILD_${_M} OFF)
endforeach()
endif()
@ -388,6 +389,7 @@ endif()
add_library(srv_modules OBJECT
src/proxy.c
src/pop3p.c
src/imapp.c
src/smtpp.c
src/ftppr.c
src/tcppm.c
@ -628,7 +630,7 @@ else()
endif()
# Build standalone proxy executables
foreach(PROXY_NAME proxy socks pop3p smtpp ftppr tcppm udppm tlspr)
foreach(PROXY_NAME proxy socks pop3p imapp smtpp ftppr tcppm udppm tlspr)
string(TOUPPER "${PROXY_NAME}" _MODULE_OPT)
if(NOT 3PROXY_BUILD_${_MODULE_OPT})
continue()
@ -679,7 +681,7 @@ foreach(PROXY_NAME proxy socks pop3p smtpp ftppr tcppm udppm tlspr)
target_link_libraries(${PROXY_NAME} PRIVATE ${WINDOWS_LIBS})
endif()
if(PROXY_NAME STREQUAL "proxy" OR PROXY_NAME STREQUAL "smtpp")
if(PROXY_NAME STREQUAL "proxy" OR PROXY_NAME STREQUAL "smtpp" OR PROXY_NAME STREQUAL "imapp")
target_sources(${PROXY_NAME} PRIVATE $<TARGET_OBJECTS:base64_obj>)
endif()
@ -723,7 +725,7 @@ install(TARGETS 3proxy 3proxy_crypt
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
foreach(PROXY_NAME proxy socks pop3p smtpp ftppr tcppm udppm tlspr)
foreach(PROXY_NAME proxy socks pop3p imapp smtpp ftppr tcppm udppm tlspr)
string(TOUPPER "${PROXY_NAME}" _MODULE_OPT)
if(3PROXY_BUILD_${_MODULE_OPT})
install(TARGETS ${PROXY_NAME}
@ -886,7 +888,7 @@ if(NOT WIN32)
)
endif()
# Module man pages installed with binary prefix only if module is built
foreach(_MAN proxy socks pop3p smtpp ftppr tcppm udppm tlspr)
foreach(_MAN proxy socks pop3p imapp smtpp ftppr tcppm udppm tlspr)
string(TOUPPER "${_MAN}" _MODULE_OPT)
if(3PROXY_BUILD_${_MODULE_OPT})
set(_MAN_SRC "${CMAKE_CURRENT_SOURCE_DIR}/man/${_MAN}.8")
@ -938,7 +940,7 @@ message(STATUS " Plugins to build: ${ALL_PLUGINS}")
message(STATUS "")
message(STATUS " Standalone modules:")
message(STATUS " Binary prefix: \"${3PROXY_BINARY_PREFIX}\"")
foreach(_M proxy socks pop3p smtpp ftppr tcppm udppm tlspr)
foreach(_M proxy socks pop3p imapp smtpp ftppr tcppm udppm tlspr)
string(TOUPPER "${_M}" _MO)
message(STATUS " BUILD_${_MO}: ${3PROXY_BUILD_${_MO}}")
endforeach()

View File

@ -84,7 +84,7 @@ install: all
if [ ! -d "$(DESTDIR)$(BINPREFIX)" ]; then mkdir -p $(DESTDIR)$(BINPREFIX)/; fi
install bin/3proxy $(DESTDIR)$(BINPREFIX)/3proxy
install bin/$(CRYPT_PREFIX)crypt $(DESTDIR)$(BINPREFIX)/$(CRYPT_PREFIX)crypt
for f in proxy socks pop3p smtpp ftppr tcppm udppm tlspr; do \
for f in proxy socks pop3p imapp smtpp ftppr tcppm udppm tlspr; do \
if [ -f bin/$(PREFIX)$$f ]; then install bin/$(PREFIX)$$f $(DESTDIR)$(BINPREFIX)/$(PREFIX)$$f; fi; \
done
install -d $(DESTDIR)$(prefix)/etc/3proxy/conf
@ -101,7 +101,7 @@ install: all
touch $(DESTDIR)$(prefix)/etc/3proxy/conf/bandlimiters
install -d $(DESTDIR)$(MANDIR)/man8
install -m 644 man/3proxy.8 $(DESTDIR)$(MANDIR)/man8/3proxy.8
for f in proxy socks pop3p smtpp ftppr tcppm udppm tlspr; do \
for f in proxy socks pop3p imapp smtpp ftppr tcppm udppm tlspr; do \
if [ -f man/$$f.8 ]; then install -m 644 man/$$f.8 $(DESTDIR)$(MANDIR)/man8/$(PREFIX)$$f.8; fi; \
done
install -m 644 man/3proxy_crypt.8 $(DESTDIR)$(MANDIR)/man8/$(CRYPT_PREFIX)crypt.8

View File

@ -94,7 +94,8 @@ INSTALL_DATA = $(INSTALL) -m 644
INSTALL_OBJS = bin/3proxy \
bin/$(CRYPT_PREFIX)crypt \
bin/$(PREFIX)ftppr \
bin/$(PREFIX)pop3p \
bin/$(PREFIX)imapp \
bin/$(PREFIX)pop3p \
bin/$(PREFIX)proxy \
bin/$(PREFIX)smtpp \
bin/$(PREFIX)socks \
@ -157,7 +158,7 @@ install-man:
$(INSTALL_BIN) -d $(MANDIR8)
$(INSTALL_DATA) man/3proxy.cfg.5 $(MANDIR5)
$(INSTALL_DATA) man/3proxy.8 $(MANDIR8)
for f in proxy socks pop3p smtpp ftppr tcppm udppm tlspr; do \
for f in proxy socks pop3p imapp smtpp ftppr tcppm udppm tlspr; do \
if [ -f man/$$f.8 ]; then $(INSTALL_DATA) man/$$f.8 $(MANDIR8)/$(PREFIX)$$f.8; fi; \
done
$(INSTALL_DATA) man/3proxy_crypt.8 $(MANDIR8)/$(CRYPT_PREFIX)crypt.8

View File

@ -86,7 +86,7 @@ install: all
if [ ! -d "$(DESTDIR)$(BINPREFIX)" ]; then mkdir -p $(DESTDIR)$(BINPREFIX)/; fi
install bin/3proxy $(DESTDIR)$(BINPREFIX)/3proxy
install bin/$(CRYPT_PREFIX)crypt $(DESTDIR)$(BINPREFIX)/$(CRYPT_PREFIX)crypt
for f in proxy socks pop3p smtpp ftppr tcppm udppm tlspr; do \
for f in proxy socks pop3p imapp smtpp ftppr tcppm udppm tlspr; do \
if [ -f bin/$(PREFIX)$$f ]; then install bin/$(PREFIX)$$f $(DESTDIR)$(BINPREFIX)/$(PREFIX)$$f; fi; \
done
install -d $(DESTDIR)$(prefix)/etc/3proxy/conf
@ -103,7 +103,7 @@ install: all
touch $(DESTDIR)$(prefix)/etc/3proxy/conf/bandlimiters
install -d $(DESTDIR)$(MANDIR)/man8
install -m 644 man/3proxy.8 $(DESTDIR)$(MANDIR)/man8/3proxy.8
for f in proxy socks pop3p smtpp ftppr tcppm udppm tlspr; do \
for f in proxy socks pop3p imapp smtpp ftppr tcppm udppm tlspr; do \
if [ -f man/$$f.8 ]; then install -m 644 man/$$f.8 $(DESTDIR)$(MANDIR)/man8/$(PREFIX)$$f.8; fi; \
done
install -m 644 man/3proxy_crypt.8 $(DESTDIR)$(MANDIR)/man8/$(CRYPT_PREFIX)crypt.8

View File

@ -33,6 +33,7 @@
<li><a href="#NAMES">How to resolve names through a parent proxy</a></li>
<li><a href="#ISFTP">How to set up an FTP proxy</a></li>
<li><a href="#TLSPR">How to set up an SNI proxy (tlspr)</a></li>
<li><a href="#DNSPR">How to set up a DNS proxy (dnspr)</a></li>
<li><a href="#SSLPLUGIN">How to set up TLS/SSL (https proxy, mTLS)</a></li>
<li><a href="#CERTIFICATES">How to create CA and certificates for SSL</a></li>
<li><a href="#PCRE">How to use PCRE filtering (regular expressions)</a></li>
@ -582,6 +583,7 @@ proxy -p8080 -i192.168.2.1
An SNI proxy can be used to transparently redirect any TLS traffic with an external router or via local redirection rules. It can also be used
to extract hostnames from TLS to use in ACLs in combination with SOCKS or HTTP(s) proxy and/or the Transparent plugin. It can also be used to require TLS or mTLS between services. The TLS handshake contains no
port information; if tlspr is used as a standalone service, the destination port may be either detected with the Transparent plugin or configured with the -P option (default 443).
Note: tlspr does not support user authentication (there are no credentials in the TLS handshake to authenticate against); use ACLs by IP or a parent proxy with authentication if access control is required.
</p><p>
<b>Options:</b>
</p><pre>
@ -592,8 +594,54 @@ proxy -p8080 -i192.168.2.1
2 - require TLS, check both client and server HELLO
3 - require TLS, check that the server sends a certificate (not compatible with TLS 1.3)
4 - require mutual TLS, check that the server sends a certificate request and the client sends a certificate (not compatible with TLS 1.3)
-Ximap | -Xpop3 | -Xsmtp - explicit TLS (STARTTLS) mode: tlspr speaks the plaintext
protocol with the client (greeting, STARTTLS command), then upgrades both sides to TLS
</pre>
<p>
<b>Implicit vs explicit TLS:</b>
</p><p>
Implicit TLS means TLS from the first byte of the connection: https (443), imaps (993), SMTP submission secure (submissions) (465).
Explicit TLS means the connection starts in plaintext and is upgraded with a STARTTLS/STLS command: imap (143), SMTP submission (587), pop3 (110).
tlspr supports both: for implicit TLS the destination host is taken from SNI and the port from -P; for explicit TLS
the -X option makes tlspr speak the plaintext protocol phase with the client (greeting, STARTTLS command) before
upgrading both sides to TLS. Example:
</p><pre>
# https (implicit)
tlspr -p443 -P443 -c1
# imaps (implicit)
tlspr -p993 -P993 -c1
# submissions (implicit)
tlspr -p465 -P465 -c1
# imap STARTTLS (explicit)
tlspr -p143 -P143 -Ximap
# submission STARTTLS (explicit)
tlspr -p587 -P587 -Xsmtp
# pop3 STLS (explicit)
tlspr -p110 -P110 -Xpop3
</pre>
<p>
Note: for explicit TLS the protocol services smtpp, imapp and pop3p can be used instead of tlspr -X; they also
support STARTTLS.
</p><p>
<b>Recommended setup - traffic redirection:</b> the most universal configuration is to redirect TLS traffic
(ports 443, 993, 465, 143, 587, 110) to tlspr with external router rules or local redirection (Transparent plugin).
The original destination address and port are preserved, no -P or per-port services are required, and both implicit
and explicit TLS work with the same installation.
</p><pre>
auth iponly
allow *
tlspr -p1443 -c1
</pre>
<p>
with, for example, iptables:
</p><pre>
iptables -t nat -A PREROUTING -p tcp -m multiport --dports 443,993,465 -j REDIRECT --to-port 1443
</pre>
<p>
Alternatively, if clients use dnspr as their DNS resolver, traffic can be redirected via DNS —
see <a href="#DNSPR">How to set up a DNS proxy (dnspr)</a>.
</p>
<p>
<b>SNI Break (DPI Bypass):</b>
<br>tlspr can be used as a parent with the "tls" type to implement SNI splitting for DPI bypass (similar to NoDPI/GoodByeDPI).
The client sends the first part of the TLS ClientHello, tlspr splits it at the SNI extension and sends it in two TCP packets,
@ -638,6 +686,47 @@ parent 1000 tls 0.0.0.0 0
deny * * blocked.example.com
allow *
proxy
</pre>
</p>
<li><a name="DNSPR"><i>How to set up a DNS proxy (dnspr)</i></a></li>
<p>
dnspr is a DNS forwarding service. It answers queries from the 3proxy name cache (including static nsrecord
entries), forwards other queries to the resolvers configured with nserver, and caches the results if
nscache/nscache6 are configured. Options:
</p><pre>
-s - simple DNS forwarding: do not use 3proxy resolver / name cache
-F&lt;ip&gt; - fake: answer all A (or AAAA) queries with the given IP address.
May be given twice - once with an IPv4 and once with an IPv6 address.
</pre>
<p>
dnspr can be used to redirect traffic by hostname, e.g. to point mail clients to a
<a href="#TLSPR">tlspr</a> installation, by adding nsrecord entries for the service hostnames
(nscache/nscache6 keep the answers for all other names intact):
</p><pre>
nscache 65536
nscache6 65536
dnspr -p53
# google
nsrecord smtp.gmail.com 10.0.0.1
nsrecord imap.gmail.com 10.0.0.1
nsrecord pop.gmail.com 10.0.0.1
# mail.ru
nsrecord smtp.mail.ru 10.0.0.1
nsrecord imap.mail.ru 10.0.0.1
nsrecord pop.mail.ru 10.0.0.1
# yandex.ru
nsrecord smtp.yandex.ru 10.0.0.1
nsrecord imap.yandex.ru 10.0.0.1
nsrecord pop.yandex.ru 10.0.0.1
</pre>
<p>
where 10.0.0.1 is the address tlspr listens on. If every hostname must be redirected, a single fake
address can be used instead of individual nsrecords:
</p><pre>
nscache 65536
nscache6 65536
dnspr -p53 -F10.0.0.1
</pre>
</p>
<li><a name="SSLPLUGIN"><i>How to set up TLS/SSL (https proxy, mTLS)</i></a>

View File

@ -33,6 +33,7 @@
<li><a href="#NAMES">Как разрешать имена на родительском прокси?</a></li>
<li><a href="#ISFTP">Как настроить FTP прокси?</a></li>
<li><a href="#TLSPR">Как настроить SNI proxy (tlspr)</a></li>
<li><a href="#DNSPR">Как настроить DNS proxy (dnspr)</a></li>
<li><a href="#SSLPLUGIN">Как настроить TLS/SSL (https прокси, mTLS)</a></li>
<li><a href="#CERTIFICATES">Как создать CA и сертификаты для SSL</a></li>
<li><a href="#PCRE">Как использовать PCRE-фильтрацию (регулярные выражения)</a></li>
@ -590,6 +591,7 @@
Еще одна задача которую может решать модуль - требование наличия TLS или mTLS (mutual TLS).
Если tlspr используется как отдельный сервис без использования плагина Transparent, то необходимо задать порт назначения через опцию -P (по умолчанию 443),
т.к. TLS хендшейк не содержит информации о порте назначения.
Примечание: tlspr не поддерживает аутентификацию пользователей (в TLS-хендшейке нет учетных данных); используйте ACL по IP или родительский прокси с аутентификацией, если требуется контроль доступа.
</p><p>
<b>Опции:</b>
</p><pre>
@ -600,8 +602,54 @@
2 - требовать TLS, проверять наличие client и server HELLO
3 - требовать TLS, проверять наличие серверного сертификата (не совместим с TLS 1.3+)
4 - требовать взаимный (mutual) TLS, проверять что сервер запрашивает сертификат и клиент его отправляет (не совместим с TLS 1.3+)
-Ximap | -Xpop3 | -Xsmtp - режим explicit TLS (STARTTLS): tlspr говорит с клиентом
на plaintext-протоколе (приветствие, команда STARTTLS), затем поднимает TLS с обеих сторон
</pre>
<p>
<b>Implicit и explicit TLS:</b>
</p><p>
Implicit TLS означает TLS с первого байта соединения: https (443), imaps (993), SMTP submission secure (submissions) (465).
Explicit TLS означает, что соединение начинается в plaintext и поднимается до TLS командой STARTTLS/STLS: imap (143), SMTP submission (587), pop3 (110).
tlspr поддерживает оба варианта: для implicit TLS хост назначения берется из SNI, а порт из -P; для explicit TLS
опция -X заставляет tlspr говорить с клиентом на plaintext-фазе протокола (приветствие, команда STARTTLS) перед
поднятием TLS с обеих сторон. Пример:
</p><pre>
# https (implicit)
tlspr -p443 -P443 -c1
# imaps (implicit)
tlspr -p993 -P993 -c1
# submissions (implicit)
tlspr -p465 -P465 -c1
# imap STARTTLS (explicit)
tlspr -p143 -P143 -Ximap
# submission STARTTLS (explicit)
tlspr -p587 -P587 -Xsmtp
# pop3 STLS (explicit)
tlspr -p110 -P110 -Xpop3
</pre>
<p>
Примечание: для explicit TLS вместо tlspr -X можно использовать протокольные сервисы smtpp, imapp и pop3p; они
также поддерживают STARTTLS.
</p><p>
<b>Рекомендуемая конфигурация - перенаправление трафика:</b> наиболее универсальная конфигурация - перенаправлять
TLS-трафик (порты 443, 993, 465, 143, 587, 110) на tlspr правилами внешнего маршрутизатора или локальными
правилами (плагин Transparent). Исходные адрес и порт назначения сохраняются, -P и отдельные сервисы для каждого
порта не требуются, implicit и explicit TLS работают в рамках одной установки.
</p><pre>
auth iponly
allow *
tlspr -p1443 -c1
</pre>
<p>
например, с iptables:
</p><pre>
iptables -t nat -A PREROUTING -p tcp -m multiport --dports 443,993,465 -j REDIRECT --to-port 1443
</pre>
<p>
Также, если клиенты используют dnspr в качестве DNS-резолвера, трафик можно перенаправлять через DNS —
см. <a href="#DNSPR">Как настроить DNS proxy (dnspr)</a>.
</p>
<p>
<b>SNI Break (обход DPI):</b>
<br>tlspr может использоваться как родительский прокси типа "tls" для реализации SNI-фрагментации (аналог NoDPI/GoodByeDPI).
Клиент отправляет первую часть TLS ClientHello, tlspr разбивает его на расширении SNI и отправляет двумя TCP-пакетами,
@ -649,6 +697,48 @@ proxy
</pre>
</p>
<li><a name="DNSPR"><i>Как настроить DNS proxy (dnspr)</i></a></li>
<p>
dnspr - сервис пересылки DNS-запросов. Он отвечает на запросы из кэша имен 3proxy (включая статические записи
nsrecord), пересылает остальные запросы на резолверы, заданные командой nserver, и кэширует результаты, если
настроены nscache/nscache6. Опции:
</p><pre>
-s - простая пересылка DNS: не использовать резолвер / кэш имен 3proxy
-F&lt;ip&gt; - fake: отвечать на все A (или AAAA) запросы заданным IP-адресом.
Может быть указана дважды - один раз с IPv4 и один раз с IPv6 адресом.
</pre>
<p>
dnspr можно использовать для перенаправления трафика по имени хоста, например, чтобы направить почтовых
клиентов на установку <a href="#TLSPR">tlspr</a>, добавив записи nsrecord для имен почтовых сервисов
(nscache/nscache6 сохраняют ответы для всех остальных имен):
</p><pre>
nscache 65536
nscache6 65536
dnspr -p53
# google
nsrecord smtp.gmail.com 10.0.0.1
nsrecord imap.gmail.com 10.0.0.1
nsrecord pop.gmail.com 10.0.0.1
# mail.ru
nsrecord smtp.mail.ru 10.0.0.1
nsrecord imap.mail.ru 10.0.0.1
nsrecord pop.mail.ru 10.0.0.1
# yandex.ru
nsrecord smtp.yandex.ru 10.0.0.1
nsrecord imap.yandex.ru 10.0.0.1
nsrecord pop.yandex.ru 10.0.0.1
</pre>
<p>
где 10.0.0.1 - адрес, на котором слушает tlspr. Если перенаправлять нужно все имена, вместо отдельных
записей nsrecord можно использовать один fake-адрес:
</p><pre>
nscache 65536
nscache6 65536
dnspr -p53 -F10.0.0.1
</pre>
</p>
<li><a name="SSLPLUGIN"><i>Как настроить TLS/SSL (https прокси, mTLS)</i></a>
<p>
Начиная с версии 0.9.7 поддержка TLS/SSL встроена в 3proxy при компиляции с OpenSSL

View File

@ -8,6 +8,7 @@
<br><A HREF="man8/3proxy_crypt.8.html">3proxy_crypt.8</A>
<br><A HREF="man8/3proxy.8.html">3proxy.8</A>
<br><A HREF="man8/ftppr.8.html">ftppr.8</A>
<br><A HREF="man8/imapp.8.html">imapp.8</A>
<br><A HREF="man8/pop3p.8.html">pop3p.8</A>
<br><A HREF="man8/proxy.8.html">proxy.8</A>
<br><A HREF="man8/smtpp.8.html">smtpp.8</A>

View File

@ -87,6 +87,7 @@ start gateway services:</p>
[options] <b><br>
socks</b> [options] <b><br>
pop3p</b> [options] <b><br>
imapp</b> [options] <b><br>
smtpp</b> [options] <b><br>
ftppr</b> [options] <b><br>
admin</b> [options] <b><br>
@ -104,6 +105,7 @@ handshake), may be used to redirect any TLS-based traffic
auto</b> Proxy with protocol autoselection between proxy /
socks / tlspr <b><br>
pop3p</b> POP3 proxy (default port 110) <b><br>
imapp</b> IMAPv4 proxy (default port 143) <b><br>
smtpp</b> SMTP proxy (default port 25) <b><br>
ftppr</b> FTP proxy (default port 21) <b><br>
admin</b> Web interface (default port 80) <b><br>
@ -220,8 +222,8 @@ information reported) <b><br>
-a2</b> (for proxy) generate Via: and X-Forwarded-For:
instead of Forwarded: <br>
Also, all options mentioned for <b>proxy</b>(8)
<b>socks</b>(8) <b>pop3p</b>(8) <b>tcppm</b>(8)
<b>udppm</b>(8) <b>ftppr</b>(8) <br>
<b>socks</b>(8) <b>pop3p</b>(8) <b>imapp</b>(8)
<b>tcppm</b>(8) <b>udppm</b>(8) <b>ftppr</b>(8) <br>
are also supported. <br>
Portmapping services listen at SRCPORT and connect to
DSTADDR:DSTPORT HTTP and SOCKS proxies are standard. <br>
@ -779,8 +781,9 @@ special case of local redirection, it works only with
<b>socks</b> proxy. In case of local redirection request is
redirected to different service, <b>ftp</b> locally
redirects to <b>ftppr pop3</b> locally redirects to <b>pop3p
http</b> locally redirects to <b>proxy admin</b> locally
redirects to the admin -s service. <br>
imap</b> locally redirects to <b>imapp http</b> locally
redirects to <b>proxy admin</b> locally redirects to the
admin -s service. <br>
Unix domain sockets can be used instead of IP address with
the syntax <i>unix:/path/to/socket</i> (e.g., parent 1000
socks5 unix:/var/run/parent.sock 1080). On Linux, abstract
@ -1294,7 +1297,8 @@ to <b>3proxy@3proxy.org</b></p>
<p style="margin-left:6%; margin-top: 1em">3proxy(8),
3proxy_crypt(8), proxy(8), ftppr(8), socks(8), pop3p(8),
smtpp(8), tlspr(8), tcppm(8), udppm(8), syslogd(8), <br>
imapp(8), smtpp(8), tlspr(8), tcppm(8), udppm(8),
syslogd(8), <br>
https://3proxy.org/</p>
<h2>AUTHORS

View File

@ -58,11 +58,11 @@ multiple gateways with HTTP and HTTPS proxy with FTP over
HTTP support, SOCKS v4, v4.5 and v5, POP3 proxy, UDP and TCP
portmappers. Each gateway is started from the configuration
file like an independent service <b>proxy</b>(8)
<b>socks</b>(8) <b>pop3p</b>(8) <b>tcppm</b>(8)
<b>udppm</b>(8) <b>ftppr</b>(8) <b>dnspr</b> but
<b>3proxy</b> is not a kind of wrapper or superserver for
these daemons. It just has the same code compiled in, but
provides much more functionality. SOCKSv5 implementation
<b>socks</b>(8) <b>pop3p</b>(8) <b>imapp</b>(8)
<b>tcppm</b>(8) <b>udppm</b>(8) <b>ftppr</b>(8) <b>dnspr</b>
but <b>3proxy</b> is not a kind of wrapper or superserver
for these daemons. It just has the same code compiled in,
but provides much more functionality. SOCKSv5 implementation
allows you to use 3proxy with any UDP or TCP based client
applications designed without proxy support (with
<i>SocksCAP</i>, <i>FreeCAP</i> or another client-side
@ -195,8 +195,8 @@ to <b>3proxy@3proxy.org</b></p>
<p style="margin-left:6%; margin-top: 1em">3proxy.cfg(5),
proxy(8), ftppr(8), socks(8), pop3p(8), tcppm(8), udppm(8),
kill(1), syslogd(8), <br>
proxy(8), ftppr(8), socks(8), pop3p(8), imapp(8), tcppm(8),
udppm(8), kill(1), syslogd(8), <br>
https://3proxy.org/</p>
<h2>AUTHORS

287
doc/html/man8/imapp.8.html Normal file
View File

@ -0,0 +1,287 @@
<!-- Creator : groff version 1.24.1 -->
<html>
<head>
</head>
<body>
<h1 align="center">imapp</h1>
<a href="#NAME">NAME</a><br>
<a href="#SYNOPSIS">SYNOPSIS</a><br>
<a href="#DESCRIPTION">DESCRIPTION</a><br>
<a href="#OPTIONS">OPTIONS</a><br>
<a href="#CLIENTS">CLIENTS</a><br>
<a href="#BUGS">BUGS</a><br>
<a href="#SEE ALSO">SEE ALSO</a><br>
<a href="#AUTHORS">AUTHORS</a><br>
<hr>
<h2>NAME
<a name="NAME"></a>
</h2>
<p style="margin-left:6%; margin-top: 1em"><b>imapp</b> -
IMAPv4 proxy gateway service</p>
<h2>SYNOPSIS
<a name="SYNOPSIS"></a>
</h2>
<p style="margin-left:6%; margin-top: 1em"><b>imapp</b>
[<b>-d</b>] [<b>-l</b>[[<i>@</i>]<i>logfile</i>]]
[<b>-p</b><i>port</i>] [<b>-i</b><i>internal_ip</i>]
[<b>-e</b><i>external_ip</i>]
[<b>-h</b><i>default_ip[:port]</i>] [<b>-x</b><i>]</i></p>
<h2>DESCRIPTION
<a name="DESCRIPTION"></a>
</h2>
<p style="margin-left:6%; margin-top: 1em"><i><b>imapp</b></i>
is IMAPv4 (IMAP4rev1) gateway service to allow internal
users to access external IMAP servers.</p>
<h2>OPTIONS
<a name="OPTIONS"></a>
</h2>
<table width="100%" border="0" rules="none" frame="void"
cellspacing="0" cellpadding="0">
<tr valign="top" align="left">
<td width="6%"></td>
<td width="3%">
<p style="margin-top: 1em"><b>-I</b></p></td>
<td width="6%"></td>
<td width="85%">
<p style="margin-top: 1em">Inetd mode. Standalone service
only.</p> </td></tr>
<tr valign="top" align="left">
<td width="6%"></td>
<td width="3%">
<p style="margin-top: 1em"><b>-d</b></p></td>
<td width="6%"></td>
<td width="85%">
<p style="margin-top: 1em">Daemonize. Detach service from
console and run in the background.</p></td></tr>
<tr valign="top" align="left">
<td width="6%"></td>
<td width="3%">
<p style="margin-top: 1em"><b>-t</b></p></td>
<td width="6%"></td>
<td width="85%">
<p style="margin-top: 1em">Be silenT. Do not log
start/stop/accept error records.</p></td></tr>
<tr valign="top" align="left">
<td width="6%"></td>
<td width="3%">
<p style="margin-top: 1em"><b>-u</b></p></td>
<td width="6%"></td>
<td width="85%">
<p style="margin-top: 1em">Never look for username
authentication.</p> </td></tr>
<tr valign="top" align="left">
<td width="6%"></td>
<td width="3%">
<p style="margin-top: 1em"><b>-e</b></p></td>
<td width="6%"></td>
<td width="85%">
<p style="margin-top: 1em">External address. IP address of
the interface the proxy should initiate connections from. By
default, the system will decide which address to use in
accordance with the routing table.</p></td></tr>
</table>
<p style="margin-left:6%;"><b>-ni</b><i>PATH</i></p>
<p style="margin-left:15%;">(Linux only) Switch to the
network namespace identified by <i>PATH</i> before opening
the listening socket. The current namespace is saved and
restored immediately after binding, so outgoing connections
run in the original namespace unless <b>-ne</b> is also
given.</p>
<p style="margin-left:6%;"><b>-ne</b><i>PATH</i></p>
<p style="margin-left:15%;">(Linux only) Switch to the
network namespace identified by <i>PATH</i> after the
listening socket has been bound (and after restoring from
<b>-ni</b> if applicable). Both options accept any namespace
file path (e.g. <i>/var/run/netns/myns</i> or
<i>/proc/PID/ns/net</i>) and require
<b>CAP_SYS_ADMIN</b>.</p>
<table width="100%" border="0" rules="none" frame="void"
cellspacing="0" cellpadding="0">
<tr valign="top" align="left">
<td width="6%"></td>
<td width="3%">
<p><b>-i</b></p></td>
<td width="6%"></td>
<td width="85%">
<p>Internal address. IP address the proxy accepts
connections to. By default, connections to any interface are
accepted. It&acute;s usually unsafe. Unix domain sockets can
be specified with <i>-iunix:/path/to/socket</i> syntax
(e.g., -iunix:/var/run/imapp.sock). On Linux, abstract
sockets use <i>-iunix:@socketname</i> syntax.</p></td></tr>
<tr valign="top" align="left">
<td width="6%"></td>
<td width="3%">
<p style="margin-top: 1em"><b>-p</b></p></td>
<td width="6%"></td>
<td width="85%">
<p style="margin-top: 1em">Port. Port proxy listens for
incoming connections. Default is 143.</p></td></tr>
<tr valign="top" align="left">
<td width="6%"></td>
<td width="3%">
<p style="margin-top: 1em"><b>-h</b></p></td>
<td width="6%"></td>
<td width="85%">
<p style="margin-top: 1em">Default destination. It&rsquo;s
used if the target address is not specified by the user.</p></td></tr>
<tr valign="top" align="left">
<td width="6%"></td>
<td width="3%">
<p style="margin-top: 1em"><b>-x</b></p></td>
<td width="6%"></td>
<td width="85%">
<p style="margin-top: 1em">Disable STARTTLS support.
STARTTLS is not announced in the CAPABILITY response and the
STARTTLS command is not accepted.</p></td></tr>
<tr valign="top" align="left">
<td width="6%"></td>
<td width="3%">
<p style="margin-top: 1em"><b>-l</b></p></td>
<td width="6%"></td>
<td width="85%">
<p style="margin-top: 1em">Log. By default logging is to
stdout. If <i>logfile</i> is specified logging is to file.
Under Unix, if &acute;<i>@</i>&acute; precedes
<i>logfile</i>, syslog is used for logging.</p></td></tr>
<tr valign="top" align="left">
<td width="6%"></td>
<td width="3%">
<p style="margin-top: 1em"><b>-S</b></p></td>
<td width="6%"></td>
<td width="85%">
<p style="margin-top: 1em">Increase or decrease stack size.
You may want to try something like -S8192 if you experience
3proxy crashes.</p></td></tr>
</table>
<h2>CLIENTS
<a name="CLIENTS"></a>
</h2>
<p style="margin-left:6%; margin-top: 1em">You can use any
MUA (Mail User Agent) with IMAPv4 support. Set the client to
use <i>internal_ip</i> and <i>port</i> as an IMAP server.
The address of the real IMAP server must be configured as a
part of the IMAP username. The format for the username is
<i>username</i>@<i>server</i>, where <i>server</i> is the
address of the IMAP server and <i>username</i> is the
user&acute;s login on this IMAP server. The login itself may
contain an &acute;@&acute; sign. Supported client
authentication methods are the LOGIN command, AUTHENTICATE
PLAIN and AUTHENTICATE LOGIN. With the server, the proxy
authenticates using the method chosen by the client if the
server supports it (as advertised in the CAPABILITY
response); otherwise it falls back to AUTHENTICATE LOGIN,
AUTHENTICATE PLAIN or the LOGIN command, in this order of
preference. Challenge-response authentication (CRAM-MD5,
etc.) is not supported, because it requires a challenge from
the server before we know which server to connect to. When
running as a 3proxy service (not as a standalone binary),
STARTTLS is supported and announced in the CAPABILITY
response unless disabled with <b>-x</b>. After the client
issues STARTTLS, the connection is handled by
<b>tlspr</b>(8): the destination host is taken from the SNI
of the client TLS handshake (or from the -h option), the
proxy performs STARTTLS negotiation with the destination
server, and then transparently passes TLS traffic between
the client and the server. If the destination server does
not support STARTTLS, the TLS handshake with the client
fails.</p>
<h2>BUGS
<a name="BUGS"></a>
</h2>
<p style="margin-left:6%; margin-top: 1em">Report all bugs
to <b>3proxy@3proxy.org</b></p>
<h2>SEE ALSO
<a name="SEE ALSO"></a>
</h2>
<p style="margin-left:6%; margin-top: 1em">3proxy(8),
ftppr(8), pop3p(8), proxy(8), smtpp(8), socks(8), tcppm(8),
tlspr(8), udppm(8), syslogd(8), <br>
https://3proxy.org/</p>
<h2>AUTHORS
<a name="AUTHORS"></a>
</h2>
<p style="margin-left:6%; margin-top: 1em">3proxy is
designed by Vladimir Dubrovin &lt;vlad@3proxy.org&gt;</p>
<hr>
</body>
</html>

View File

@ -36,15 +36,16 @@ POP3 proxy gateway service</p>
[<b>-d</b>] [<b>-l</b>[[<i>@</i>]<i>logfile</i>]]
[<b>-p</b><i>port</i>] [<b>-i</b><i>internal_ip</i>]
[<b>-e</b><i>external_ip</i>]
[<b>-h</b><i>default_ip[:port]</i>]</p>
[<b>-h</b><i>default_ip[:port]</i>] [<b>-x</b><i>]</i></p>
<h2>DESCRIPTION
<a name="DESCRIPTION"></a>
</h2>
<p style="margin-left:6%; margin-top: 1em"><b>pop3p</b> is
POP3 gateway service to allow internal users to access
<p style="margin-left:6%; margin-top: 1em"><i><b>pop3p</b></i>
is POP3 gateway service to allow internal users to access
external POP3 servers.</p>
<h2>OPTIONS
@ -184,6 +185,19 @@ used if the target address is not specified by the user.</p></td></tr>
<td width="3%">
<p style="margin-top: 1em"><b>-x</b></p></td>
<td width="6%"></td>
<td width="85%">
<p style="margin-top: 1em">Disable STARTTLS (STLS) support.
STLS is not announced in the CAPA response and the STLS
command is not accepted.</p></td></tr>
<tr valign="top" align="left">
<td width="6%"></td>
<td width="3%">
<p style="margin-top: 1em"><b>-l</b></p></td>
<td width="6%"></td>
<td width="85%">
@ -224,8 +238,17 @@ user&acute;s login on this POP3 server. The login itself may
contain an &acute;@&acute; sign. Only cleartext
authentication is supported, because challenge-response
authentication (APOP, CRAM-MD5, etc.) requires a challenge
from the server before we know which server to connect
to.</p>
from the server before we know which server to connect to.
When running as a 3proxy service (not as a standalone
binary), STLS is supported and announced in the CAPA
response unless disabled with <b>-x</b>. After the client
issues STLS, the connection is handled by <b>tlspr</b>(8):
the destination host is taken from the SNI of the client TLS
handshake (or from the -h option), the proxy performs STLS
negotiation with the destination server, and then
transparently passes TLS traffic between the client and the
server. If the destination server does not support STLS, the
TLS handshake with the client fails.</p>
<h2>BUGS
<a name="BUGS"></a>

View File

@ -36,15 +36,16 @@ SMTP proxy gateway service</p>
[<b>-d</b>] [<b>-l</b>[[<i>@</i>]<i>logfile</i>]]
[<b>-p</b><i>port</i>] [<b>-i</b><i>internal_ip</i>]
[<b>-e</b><i>external_ip</i>]
[<b>-h</b><i>default_ip[:port]</i>]</p>
[<b>-h</b><i>default_ip[:port]</i>] [<b>-x</b><i>]</i></p>
<h2>DESCRIPTION
<a name="DESCRIPTION"></a>
</h2>
<p style="margin-left:6%; margin-top: 1em"><b>smtpp</b> is
SMTP gateway service to allow internal users to access
<p style="margin-left:6%; margin-top: 1em"><i><b>smtpp</b></i>
is SMTP gateway service to allow internal users to access
external SMTP servers.</p>
<h2>OPTIONS
@ -166,7 +167,7 @@ sockets use <i>-iunix:@socketname</i> syntax.</p></td></tr>
<p style="margin-top: 1em">Port. Port proxy listens for
incoming connections. Default is 25.</p></td></tr>
incoming connections. Default is 587.</p></td></tr>
<tr valign="top" align="left">
<td width="6%"></td>
<td width="3%">
@ -184,6 +185,19 @@ used if the target address is not specified by the user.</p></td></tr>
<td width="3%">
<p style="margin-top: 1em"><b>-x</b></p></td>
<td width="6%"></td>
<td width="85%">
<p style="margin-top: 1em">Disable STARTTLS support.
STARTTLS is not announced in the EHLO response and the
STARTTLS command is not accepted.</p></td></tr>
<tr valign="top" align="left">
<td width="6%"></td>
<td width="3%">
<p style="margin-top: 1em"><b>-l</b></p></td>
<td width="6%"></td>
<td width="85%">
@ -225,7 +239,17 @@ server. The login itself may contain an &acute;@&acute;
sign. Only cleartext authentication is supported, because
challenge-response authentication (CRAM-MD5, SPA, etc.)
requires a challenge from the server before we know which
server to connect to.</p>
server to connect to. When running as a 3proxy service (not
as a standalone binary), STARTTLS is supported and announced
in the EHLO response unless disabled with <b>-x</b>. After
the client issues STARTTLS, the connection is handled by
<b>tlspr</b>(8): the destination host is taken from the SNI
of the client TLS handshake (or from the -h option), the
proxy performs STARTTLS negotiation with the destination
server, and then transparently passes TLS traffic between
the client and the server. If the destination server does
not support STARTTLS, the TLS handshake with the client
fails.</p>
<h2>BUGS
<a name="BUGS"></a>

View File

@ -49,7 +49,9 @@ SNI proxy gateway service</p>
an SNI gateway service (destination host is taken from TLS
handshake). The destination port must be specified via the
-P option (or it may be detected with the Transparent
plugin).</p>
plugin). tlspr does not support user authentication; use
ACLs by client IP or a parent proxy with authentication if
access control is required.</p>
<h2>OPTIONS
<a name="OPTIONS"></a>
@ -241,27 +243,45 @@ with TLS 1.3)</p></td></tr>
packet across multiple TCP segments to make SNI-based DPI
detection harder. An optional numeric value can follow (e.g.
<b>-s1</b>) to control the splitting behaviour.</p></td></tr>
</table>
<p style="margin-left:6%;"><b>-Ximap | -Xpop3 |
-Xsmtp</b></p>
<p style="margin-left:15%;">STARTTLS mode for the given
protocol. The proxy speaks the plaintext protocol with the
client (greeting, capability advertisement with STARTTLS
only, STARTTLS command), then, after the client issues
STARTTLS and sends a TLS Client HELLO, connects to the
destination taken from SNI (default port 143/110/587),
performs STARTTLS negotiation with the destination server
and transparently passes TLS traffic. If the destination
server does not support STARTTLS, the TLS handshake with the
client fails.</p>
<table width="100%" border="0" rules="none" frame="void"
cellspacing="0" cellpadding="0">
<tr valign="top" align="left">
<td width="6%"></td>
<td width="4%">
<td width="3%">
<p style="margin-top: 1em"><b>-l</b></p></td>
<td width="5%"></td>
<p><b>-l</b></p></td>
<td width="6%"></td>
<td width="85%">
<p style="margin-top: 1em">Log. By default logging is to
stdout. If <i>logfile</i> is specified logging is to file.
Under Unix, if &acute;<i>@</i>&acute; precedes
<i>logfile</i>, syslog is used for logging.</p></td></tr>
<p>Log. By default logging is to stdout. If <i>logfile</i>
is specified logging is to file. Under Unix, if
&acute;<i>@</i>&acute; precedes <i>logfile</i>, syslog is
used for logging.</p></td></tr>
<tr valign="top" align="left">
<td width="6%"></td>
<td width="4%">
<td width="3%">
<p style="margin-top: 1em"><b>-S</b></p></td>
<td width="5%"></td>
<td width="6%"></td>
<td width="85%">

View File

@ -29,6 +29,7 @@ from the configuration file like an independent service
.BR proxy (8)
.BR socks (8)
.BR pop3p (8)
.BR imapp (8)
.BR tcppm (8)
.BR udppm (8)
.BR ftppr (8)
@ -140,7 +141,7 @@ configuration file
Report all bugs to
.BR 3proxy@3proxy.org
.SH SEE ALSO
3proxy.cfg(5), proxy(8), ftppr(8), socks(8), pop3p(8), tcppm(8), udppm(8),
3proxy.cfg(5), proxy(8), ftppr(8), socks(8), pop3p(8), imapp(8), tcppm(8), udppm(8),
kill(1), syslogd(8),
.br
https://3proxy.org/

View File

@ -55,6 +55,9 @@ Recursion is not allowed.
.B pop3p
[options]
.br
.B imapp
[options]
.br
.B smtpp
[options]
.br
@ -92,6 +95,9 @@ Proxy with protocol autoselection between proxy / socks / tlspr
.B pop3p
POP3 proxy (default port 110)
.br
.B imapp
IMAPv4 proxy (default port 143)
.br
.B smtpp
SMTP proxy (default port 25)
.br
@ -209,6 +215,7 @@ Never ask for username/password
.BR proxy (8)
.BR socks (8)
.BR pop3p (8)
.BR imapp (8)
.BR tcppm (8)
.BR udppm (8)
.BR ftppr (8)
@ -847,6 +854,9 @@ locally redirects to
.B pop3
locally redirects to
.B pop3p
.B imap
locally redirects to
.B imapp
.B http
locally redirects to
.B proxy
@ -1384,7 +1394,7 @@ authentication and/or allow/deny ACLs.
Report all bugs to
.BR 3proxy@3proxy.org
.SH SEE ALSO
3proxy(8), 3proxy_crypt(8), proxy(8), ftppr(8), socks(8), pop3p(8), smtpp(8), tlspr(8), tcppm(8), udppm(8), syslogd(8),
3proxy(8), 3proxy_crypt(8), proxy(8), ftppr(8), socks(8), pop3p(8), imapp(8), smtpp(8), tlspr(8), tcppm(8), udppm(8), syslogd(8),
.br
https://3proxy.org/
.SH AUTHORS

124
man/imapp.8 Normal file
View File

@ -0,0 +1,124 @@
.TH imapp "8" "July 2026" "3proxy 0.9" "Universal proxy server"
.SH NAME
.B imapp
\- IMAPv4 proxy gateway service
.SH SYNOPSIS
.BR "imapp " [ -d ]
.IB \fR[ -l \fR[ \fR[ @ \fR] logfile \fR]]
.IB \fR[ -p port\fR]
.IB \fR[ -i internal_ip\fR]
.IB \fR[ -e external_ip\fR]
.IB \fR[ -h default_ip[:port]\fR]
.IB \fR[ -x ]
.SH DESCRIPTION
.B imapp
is IMAPv4 (IMAP4rev1) gateway service to allow internal users to access external
IMAP servers.
.SH OPTIONS
.TP
.B -I
Inetd mode. Standalone service only.
.TP
.B -d
Daemonize. Detach service from console and run in the background.
.TP
.B -t
Be silenT. Do not log start/stop/accept error records.
.TP
.B -u
Never look for username authentication.
.TP
.B -e
External address. IP address of the interface the proxy should initiate connections
from.
By default, the system will decide which address to use in accordance
with the routing table.
.TP
.B \-ni\fIPATH\fR
(Linux only) Switch to the network namespace identified by
.I PATH
before opening the listening socket. The current namespace is saved and restored
immediately after binding, so outgoing connections run in the original namespace
unless
.B \-ne
is also given.
.TP
.B \-ne\fIPATH\fR
(Linux only) Switch to the network namespace identified by
.I PATH
after the listening socket has been bound (and after restoring from
.B \-ni
if applicable). Both options accept any namespace file path
(e.g.\& \fI/var/run/netns/myns\fR or \fI/proc/PID/ns/net\fR)
and require \fBCAP_SYS_ADMIN\fR.
.TP
.B -i
Internal address. IP address the proxy accepts connections to.
By default, connections to any interface are accepted. It\'s usually unsafe.
Unix domain sockets can be specified with
.I -iunix:/path/to/socket
syntax (e.g., -iunix:/var/run/imapp.sock). On Linux, abstract sockets use
.I -iunix:@socketname
syntax.
.TP
.B -p
Port. Port proxy listens for incoming connections. Default is 143.
.TP
.B -h
Default destination. It's used if the target address is not specified by the user.
.TP
.B -x
Disable STARTTLS support. STARTTLS is not announced in the CAPABILITY
response and the STARTTLS command is not accepted.
.TP
.B -l
Log. By default logging is to stdout. If
.I logfile
is specified logging is to file. Under Unix, if
.RI \' @ \'
precedes
.IR logfile ,
syslog is used for logging.
.TP
.B -S
Increase or decrease stack size. You may want to try something like -S8192 if you experience 3proxy
crashes.
.SH CLIENTS
You can use any MUA (Mail User Agent) with IMAPv4 support. Set the client to use
.I internal_ip
and
.IR port
as an IMAP server. The address of the real IMAP server must be configured as a part of
the IMAP username. The format for the username is
.IR username @ server ,
where
.I server
is the address of the IMAP server and
.I username
is the user\'s login on this IMAP server. The login itself may contain an \'@\' sign.
Supported client authentication methods are the LOGIN command, AUTHENTICATE PLAIN
and AUTHENTICATE LOGIN. With the server, the proxy authenticates using the method
chosen by the client if the server supports it (as advertised in the CAPABILITY
response); otherwise it falls back to AUTHENTICATE LOGIN, AUTHENTICATE PLAIN or
the LOGIN command, in this order of preference. Challenge-response authentication
(CRAM-MD5, etc.) is not supported, because it requires a challenge from the server
before we know which server to connect to.
When running as a 3proxy service (not as a standalone binary), STARTTLS is
supported and announced in the CAPABILITY response unless disabled with
.BR -x .
After the client issues STARTTLS, the connection is handled by
.BR tlspr (8):
the destination host is taken from the SNI of the client TLS handshake (or from
the -h option), the proxy performs STARTTLS negotiation with the destination
server, and then transparently passes TLS traffic between the client and the
server. If the destination server does not support STARTTLS, the TLS handshake
with the client fails.
.SH BUGS
Report all bugs to
.BR 3proxy@3proxy.org
.SH SEE ALSO
3proxy(8), ftppr(8), pop3p(8), proxy(8), smtpp(8), socks(8), tcppm(8), tlspr(8), udppm(8), syslogd(8),
.br
https://3proxy.org/
.SH AUTHORS
3proxy is designed by Vladimir Dubrovin <vlad@3proxy.org>

View File

@ -9,6 +9,7 @@
.IB \fR[ -i internal_ip\fR]
.IB \fR[ -e external_ip\fR]
.IB \fR[ -h default_ip[:port]\fR]
.IB \fR[ -x ]
.SH DESCRIPTION
.B pop3p
is POP3 gateway service to allow internal users to access external POP3
@ -66,6 +67,10 @@ Port. Port proxy listens for incoming connections. Default is 110.
.B -h
Default destination. It's used if the target address is not specified by the user.
.TP
.B -x
Disable STARTTLS (STLS) support. STLS is not announced in the CAPA response
and the STLS command is not accepted.
.TP
.B -l
Log. By default logging is to stdout. If
.I logfile
@ -94,6 +99,16 @@ is the user\'s login on this POP3 server. The login itself may contain an \'@\'
Only cleartext authentication is supported, because challenge-response
authentication (APOP, CRAM-MD5, etc.) requires a challenge from the server before
we know which server to connect to.
When running as a 3proxy service (not as a standalone binary), STLS is
supported and announced in the CAPA response unless disabled with
.BR -x .
After the client issues STLS, the connection is handled by
.BR tlspr (8):
the destination host is taken from the SNI of the client TLS handshake (or from
the -h option), the proxy performs STLS negotiation with the destination
server, and then transparently passes TLS traffic between the client and the
server. If the destination server does not support STLS, the TLS handshake
with the client fails.
.SH BUGS
Report all bugs to
.BR 3proxy@3proxy.org

View File

@ -9,6 +9,7 @@
.IB \fR[ -i internal_ip\fR]
.IB \fR[ -e external_ip\fR]
.IB \fR[ -h default_ip[:port]\fR]
.IB \fR[ -x ]
.SH DESCRIPTION
.B smtpp
is SMTP gateway service to allow internal users to access external SMTP
@ -61,11 +62,15 @@ syntax (e.g., -iunix:/var/run/smtpp.sock). On Linux, abstract sockets use
syntax.
.TP
.B -p
Port. Port proxy listens for incoming connections. Default is 25.
Port. Port proxy listens for incoming connections. Default is 587.
.TP
.B -h
Default destination. It's used if the target address is not specified by the user.
.TP
.B -x
Disable STARTTLS support. STARTTLS is not announced in the EHLO response
and the STARTTLS command is not accepted.
.TP
.B -l
Log. By default logging is to stdout. If
.I logfile
@ -95,6 +100,16 @@ is the user\'s login on this SMTP server. The login itself may contain an \'@\'
Only cleartext authentication is supported, because challenge-response
authentication (CRAM-MD5, SPA, etc.) requires a challenge from the server before
we know which server to connect to.
When running as a 3proxy service (not as a standalone binary), STARTTLS is
supported and announced in the EHLO response unless disabled with
.BR -x .
After the client issues STARTTLS, the connection is handled by
.BR tlspr (8):
the destination host is taken from the SNI of the client TLS handshake (or from
the -h option), the proxy performs STARTTLS negotiation with the destination
server, and then transparently passes TLS traffic between the client and the
server. If the destination server does not support STARTTLS, the TLS handshake
with the client fails.
.SH BUGS
Report all bugs to
.BR 3proxy@3proxy.org

View File

@ -13,6 +13,7 @@
.SH DESCRIPTION
.B tlspr
is an SNI gateway service (destination host is taken from TLS handshake). The destination port must be specified via the -P option (or it may be detected with the Transparent plugin).
tlspr does not support user authentication; use ACLs by client IP or a parent proxy with authentication if access control is required.
.SH OPTIONS
.TP
.B -I
@ -78,6 +79,15 @@ TLS_CHECK_LEVEL. 0 (default) - allow non-TLS traffic to pass, 1 - require TLS, o
.B -s
Split the TLS Client HELLO packet across multiple TCP segments to make SNI-based DPI detection harder. An optional numeric value can follow (e.g. \fB-s1\fR) to control the splitting behaviour.
.TP
.B -Ximap | -Xpop3 | -Xsmtp
STARTTLS mode for the given protocol. The proxy speaks the plaintext protocol
with the client (greeting, capability advertisement with STARTTLS only, STARTTLS
command), then, after the client issues STARTTLS and sends a TLS Client HELLO,
connects to the destination taken from SNI (default port 143/110/587), performs
STARTTLS negotiation with the destination server and transparently passes TLS
traffic. If the destination server does not support STARTTLS, the TLS handshake
with the client fails.
.TP
.B -l
Log. By default logging is to stdout. If
.I logfile

View File

@ -537,6 +537,7 @@ int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int
#endif
freeconf(&conf);
initcommands();
res = readconfig(fp);
conf.version++;

View File

@ -2,7 +2,7 @@
# 3 proxy common Makefile
#
all: $(BUILDDIR)3proxy$(EXESUFFICS) $(BUILDDIR)$(CRYPT_PREFIX)crypt$(EXESUFFICS) $(BUILDDIR)$(PREFIX)pop3p$(EXESUFFICS) $(BUILDDIR)$(PREFIX)smtpp$(EXESUFFICS) $(BUILDDIR)$(PREFIX)ftppr$(EXESUFFICS) $(BUILDDIR)$(PREFIX)tcppm$(EXESUFFICS) $(BUILDDIR)$(PREFIX)udppm$(EXESUFFICS) $(BUILDDIR)$(PREFIX)tlspr$(EXESUFFICS) $(BUILDDIR)$(PREFIX)socks$(EXESUFFICS) $(BUILDDIR)$(PREFIX)proxy$(EXESUFFICS) allplugins
all: $(BUILDDIR)3proxy$(EXESUFFICS) $(BUILDDIR)$(CRYPT_PREFIX)crypt$(EXESUFFICS) $(BUILDDIR)$(PREFIX)pop3p$(EXESUFFICS) $(BUILDDIR)$(PREFIX)imapp$(EXESUFFICS) $(BUILDDIR)$(PREFIX)smtpp$(EXESUFFICS) $(BUILDDIR)$(PREFIX)ftppr$(EXESUFFICS) $(BUILDDIR)$(PREFIX)tcppm$(EXESUFFICS) $(BUILDDIR)$(PREFIX)udppm$(EXESUFFICS) $(BUILDDIR)$(PREFIX)tlspr$(EXESUFFICS) $(BUILDDIR)$(PREFIX)socks$(EXESUFFICS) $(BUILDDIR)$(PREFIX)proxy$(EXESUFFICS) allplugins
sockmap$(OBJSUFFICS): sockmap.c proxy.h structures.h
$(CC) $(CFLAGS) sockmap.c
@ -31,6 +31,9 @@ proxy$(OBJSUFFICS): proxy.c proxy.h structures.h proxymain.c
pop3p$(OBJSUFFICS): pop3p.c proxy.h structures.h proxymain.c
$(CC) $(CFLAGS) $(DEFINEOPTION)WITHMAIN $(DEFINEOPTION)NOPORTMAP $(DEFINEOPTION)NOUDPMAIN pop3p.c
imapp$(OBJSUFFICS): imapp.c proxy.h structures.h proxymain.c
$(CC) $(CFLAGS) $(DEFINEOPTION)WITHMAIN $(DEFINEOPTION)NOPORTMAP $(DEFINEOPTION)NOUDPMAIN imapp.c
smtpp$(OBJSUFFICS): smtpp.c proxy.h structures.h proxymain.c
$(CC) $(CFLAGS) $(DEFINEOPTION)WITHMAIN $(DEFINEOPTION)NOPORTMAP $(DEFINEOPTION)NOUDPMAIN smtpp.c
@ -59,6 +62,9 @@ $(BUILDDIR)$(PREFIX)proxy$(EXESUFFICS): sockmap$(OBJSUFFICS) proxy$(OBJSUFFICS)
$(BUILDDIR)$(PREFIX)pop3p$(EXESUFFICS): sockmap$(OBJSUFFICS) pop3p$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) $(COMPATLIBS)
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)pop3p$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) pop3p$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)
$(BUILDDIR)$(PREFIX)imapp$(EXESUFFICS): sockmap$(OBJSUFFICS) imapp$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) base64$(OBJSUFFICS) $(COMPATLIBS)
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)imapp$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) imapp$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) base64$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)
$(BUILDDIR)$(PREFIX)smtpp$(EXESUFFICS): sockmap$(OBJSUFFICS) smtpp$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) base64$(OBJSUFFICS) $(COMPATLIBS)
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)smtpp$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) smtpp$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) base64$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)
@ -86,6 +92,9 @@ srvproxy$(OBJSUFFICS): proxy.c proxy.h structures.h
srvpop3p$(OBJSUFFICS): pop3p.c proxy.h structures.h
$(CC) $(COUT)srvpop3p$(OBJSUFFICS) $(CFLAGS) pop3p.c
srvimapp$(OBJSUFFICS): imapp.c proxy.h structures.h
$(CC) $(COUT)srvimapp$(OBJSUFFICS) $(CFLAGS) imapp.c
srvsmtpp$(OBJSUFFICS): smtpp.c proxy.h structures.h
$(CC) $(COUT)srvsmtpp$(OBJSUFFICS) $(CFLAGS) smtpp.c
@ -179,6 +188,6 @@ ssl$(OBJSUFFICS): ssl.c structures.h proxy.h ssl.h
pcre$(OBJSUFFICS): pcre.c structures.h
$(CC) $(COUT)pcre$(OBJSUFFICS) $(CFLAGS) $(DEFINEOPTION)WITH_PCRE pcre.c
$(BUILDDIR)3proxy$(EXESUFFICS): 3proxy$(OBJSUFFICS) mainfunc$(OBJSUFFICS) srvproxy$(OBJSUFFICS) srvpop3p$(OBJSUFFICS) srvsmtpp$(OBJSUFFICS) srvftppr$(OBJSUFFICS) srvsocks$(OBJSUFFICS) srvtcppm$(OBJSUFFICS) srvtlspr$(OBJSUFFICS) srvauto$(OBJSUFFICS) srvudppm$(OBJSUFFICS) sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) auth$(OBJSUFFICS) acl$(OBJSUFFICS) limiter$(OBJSUFFICS) redirect$(OBJSUFFICS) authradius$(OBJSUFFICS) hash$(OBJSUFFICS) hashtables$(OBJSUFFICS) resolve$(OBJSUFFICS) sql$(OBJSUFFICS) conf$(OBJSUFFICS) log$(OBJSUFFICS) datatypes$(OBJSUFFICS) md4$(OBJSUFFICS) md5$(OBJSUFFICS) blake2$(OBJSUFFICS) 3proxy_crypt$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) stringtable$(OBJSUFFICS) srvwebadmin$(OBJSUFFICS) srvdnspr$(OBJSUFFICS) plugins$(OBJSUFFICS) mdhash$(OBJSUFFICS) $(SSL_OBJS) $(PCRE_OBJS) $(COMPATLIBS) $(VERSIONDEP)
$(LN) $(LNOUT)$(BUILDDIR)3proxy$(EXESUFFICS) $(LDFLAGS) $(VERFILE) 3proxy$(OBJSUFFICS) mainfunc$(OBJSUFFICS) auth$(OBJSUFFICS) acl$(OBJSUFFICS) limiter$(OBJSUFFICS) redirect$(OBJSUFFICS) authradius$(OBJSUFFICS) hash$(OBJSUFFICS) hashtables$(OBJSUFFICS) resolve$(OBJSUFFICS) sql$(OBJSUFFICS) conf$(OBJSUFFICS) datatypes$(OBJSUFFICS) srvauto$(OBJSUFFICS) srvproxy$(OBJSUFFICS) srvpop3p$(OBJSUFFICS) srvsmtpp$(OBJSUFFICS) srvftppr$(OBJSUFFICS) srvsocks$(OBJSUFFICS) srvtcppm$(OBJSUFFICS) srvtlspr$(OBJSUFFICS) srvudppm$(OBJSUFFICS) sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) 3proxy_crypt$(OBJSUFFICS) md4$(OBJSUFFICS) md5$(OBJSUFFICS) blake2$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) stringtable$(OBJSUFFICS) srvwebadmin$(OBJSUFFICS) srvdnspr$(OBJSUFFICS) plugins$(OBJSUFFICS) mdhash$(OBJSUFFICS) $(SSL_OBJS) $(PCRE_OBJS) $(COMPATLIBS) $(LIBS) $(PCRE_LIBS)
$(BUILDDIR)3proxy$(EXESUFFICS): 3proxy$(OBJSUFFICS) mainfunc$(OBJSUFFICS) srvproxy$(OBJSUFFICS) srvpop3p$(OBJSUFFICS) srvimapp$(OBJSUFFICS) srvsmtpp$(OBJSUFFICS) srvftppr$(OBJSUFFICS) srvsocks$(OBJSUFFICS) srvtcppm$(OBJSUFFICS) srvtlspr$(OBJSUFFICS) srvauto$(OBJSUFFICS) srvudppm$(OBJSUFFICS) sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) auth$(OBJSUFFICS) acl$(OBJSUFFICS) limiter$(OBJSUFFICS) redirect$(OBJSUFFICS) authradius$(OBJSUFFICS) hash$(OBJSUFFICS) hashtables$(OBJSUFFICS) resolve$(OBJSUFFICS) sql$(OBJSUFFICS) conf$(OBJSUFFICS) log$(OBJSUFFICS) datatypes$(OBJSUFFICS) md4$(OBJSUFFICS) md5$(OBJSUFFICS) blake2$(OBJSUFFICS) 3proxy_crypt$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) stringtable$(OBJSUFFICS) srvwebadmin$(OBJSUFFICS) srvdnspr$(OBJSUFFICS) plugins$(OBJSUFFICS) mdhash$(OBJSUFFICS) $(SSL_OBJS) $(PCRE_OBJS) $(COMPATLIBS) $(VERSIONDEP)
$(LN) $(LNOUT)$(BUILDDIR)3proxy$(EXESUFFICS) $(LDFLAGS) $(VERFILE) 3proxy$(OBJSUFFICS) mainfunc$(OBJSUFFICS) auth$(OBJSUFFICS) acl$(OBJSUFFICS) limiter$(OBJSUFFICS) redirect$(OBJSUFFICS) authradius$(OBJSUFFICS) hash$(OBJSUFFICS) hashtables$(OBJSUFFICS) resolve$(OBJSUFFICS) sql$(OBJSUFFICS) conf$(OBJSUFFICS) datatypes$(OBJSUFFICS) srvauto$(OBJSUFFICS) srvproxy$(OBJSUFFICS) srvpop3p$(OBJSUFFICS) srvimapp$(OBJSUFFICS) srvsmtpp$(OBJSUFFICS) srvftppr$(OBJSUFFICS) srvsocks$(OBJSUFFICS) srvtcppm$(OBJSUFFICS) srvtlspr$(OBJSUFFICS) srvudppm$(OBJSUFFICS) sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) 3proxy_crypt$(OBJSUFFICS) md4$(OBJSUFFICS) md5$(OBJSUFFICS) blake2$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) stringtable$(OBJSUFFICS) srvwebadmin$(OBJSUFFICS) srvdnspr$(OBJSUFFICS) plugins$(OBJSUFFICS) mdhash$(OBJSUFFICS) $(SSL_OBJS) $(PCRE_OBJS) $(COMPATLIBS) $(LIBS) $(PCRE_LIBS)

View File

@ -499,6 +499,14 @@ int parsehostname(char *hostname, struct clientparam *param, uint16_t port){
if(se){
*se = 0;
}
if(!*hostname){
if(sp){
port = atoi(sp+1);
*sp = ':';
}
*SAPORT(&param->req) = htons(port);
return 0;
}
if(hostname != (char *)param->hostname){
if(param->hostname) free(param->hostname);
param->hostname = (unsigned char *)strdup(hostname + (se!=0));
@ -553,14 +561,14 @@ int parseconnusername(char *username, struct clientparam *param, int extpasswd,
if(!username || !*username) return 1;
if ((sb=strchr(username, conf.delimchar)) == NULL){
if(!param->hostname && param->remsock == INVALID_SOCKET) return 2;
if(param->hostname)parsehostname((char *)param->hostname, param, port);
if(param->hostname)parsehostname((char *)param->hostname, param, *SAPORT(&param->req)? ntohs(*SAPORT(&param->req)) : port);
return parseusername(username, param, extpasswd);
}
while ((se=strchr(sb+1, conf.delimchar)))sb=se;
*(sb) = 0;
if(parseusername(username, param, extpasswd)) return 3;
*(sb) = conf.delimchar;
if(parsehostname(sb+1, param, port)) return 4;
if(parsehostname(sb+1, param, *SAPORT(&param->req)? ntohs(*SAPORT(&param->req)) : port)) return 4;
return 0;
}
@ -872,3 +880,21 @@ uint32_t getip46(int family, unsigned char *name, struct sockaddr *sa){
return 0;
#endif
}
int hascap(const unsigned char *line, const char *cap){
int len = (int)strlen(cap);
for(; *line; line++) if(!strncasecmp((char *)line, cap, len)) return 1;
return 0;
}
int getmultiline(struct clientparam *param, DIRECTION which, unsigned char *buf, int bufsize, const char *cap, int *found){
int i;
do {
i = sockgetlinebuf(param, which, buf, bufsize, '\n', conf.timeouts[STRING_L]);
if(i > 0 && cap && found && !*found){
buf[i] = 0;
if(hascap(buf, cap)) *found = 1;
}
} while (i > 3 && buf[3] == '-');
return i;
}

View File

@ -191,14 +191,21 @@ static int h_proxy(int argc, unsigned char ** argv){
childdef.port = 110;
childdef.isudp = 0;
childdef.service = S_POP3P;
childdef.helpmessage = " -hdefault_host[:port] - use this host and port as default if no host specified\n";
childdef.helpmessage = " -hdefault_host[:port] - use this host and port as default if no host specified\n -x - disable STARTTLS\n";
}
else if(!strcmp((char *)argv[0], "imapp")) {
childdef.pf = imappchild;
childdef.port = 143;
childdef.isudp = 0;
childdef.service = S_IMAPP;
childdef.helpmessage = " -hdefault_host[:port] - use this host and port as default if no host specified\n -x - disable STARTTLS\n";
}
else if(!strcmp((char *)argv[0], "smtpp")) {
childdef.pf = smtppchild;
childdef.port = 25;
childdef.port = 587;
childdef.isudp = 0;
childdef.service = S_SMTPP;
childdef.helpmessage = " -hdefault_host[:port] - use this host and port as default if no host specified\n";
childdef.helpmessage = " -hdefault_host[:port] - use this host and port as default if no host specified\n -x - disable STARTTLS\n";
}
else if(!strcmp((char *)argv[0], "ftppr")) {
childdef.pf = ftpprchild;
@ -257,7 +264,7 @@ static int h_proxy(int argc, unsigned char ** argv){
childdef.port = 53;
childdef.isudp = 1;
childdef.service = S_DNSPR;
childdef.helpmessage = " -s - simple DNS forwarding - do not use 3proxy resolver / name cache\n";
childdef.helpmessage = " -s - simple DNS forwarding - do not use 3proxy resolver / name cache\n -Fip - fake: answer all A queries with this IP\n";
#ifndef NOIPV6
if(!resolvfunc || (resolvfunc == myresolver && !dns_table.poolsize) || resolvfunc == fakeresolver){
fprintf(stderr, "[line %d] Warning: no nserver/nscache configured, dnspr will not work as expected\n", linenum);
@ -743,6 +750,7 @@ struct redirdesc redirs[] = {
{R_SOCKS5, "socks5", sockschild},
{R_HTTP, "http", proxychild},
{R_POP3, "pop3", pop3pchild},
{R_IMAP, "imap", imappchild},
{R_SMTP, "smtp", smtppchild},
{R_FTP, "ftp", ftpprchild},
{R_CONNECTP, "connect+", proxychild},
@ -1603,88 +1611,94 @@ static int h_chroot(int argc, unsigned char **argv){
#endif
struct commands specificcommands[]={
#ifndef _WIN32
{specificcommands+1, "setuid", h_setuid, 2, 2},
{specificcommands+2, "setgid", h_setgid, 2, 2},
{specificcommands+3, "chroot", h_chroot, 2, 4},
struct commands commandhandlers[]={
{NULL, "", h_noop, 1, 0},
{NULL, "proxy", h_proxy, 1, 0},
{NULL, "pop3p", h_proxy, 1, 0},
{NULL, "imapp", h_proxy, 1, 0},
{NULL, "ftppr", h_proxy, 1, 0},
{NULL, "socks", h_proxy, 1, 0},
{NULL, "tcppm", h_proxy, 4, 0},
{NULL, "udppm", h_proxy, 4, 0},
{NULL, "admin", h_proxy, 1, 0},
{NULL, "dnspr", h_proxy, 1, 0},
{NULL, "internal", h_internal, 2, 2},
{NULL, "external", h_external, 2, 2},
{NULL, "log", h_log, 1, 0},
{NULL, "service", h_service, 1, 1},
{NULL, "daemon", h_daemon, 1, 1},
{NULL, "config", h_config, 2, 2},
{NULL, "include", h_include, 2, 2},
{NULL, "archiver", h_archiver, 3, 0},
{NULL, "counter", h_counter, 2, 4},
{NULL, "rotate", h_rotate, 2, 2},
{NULL, "logformat", h_logformat, 2, 2},
{NULL, "timeouts", h_timeouts, 2, 0},
{NULL, "auth", h_auth, 2, 0},
{NULL, "users", h_users, 1, 0},
{NULL, "maxconn", h_maxconn, 2, 2},
{NULL, "flush", h_flush, 1, 1},
{NULL, "nserver", h_nserver, 2, 2},
{NULL, "fakeresolve", h_fakeresolve, 1, 1},
{NULL, "nscache", h_nscache, 2, 2},
{NULL, "nscache6", h_nscache6, 2, 2},
{NULL, "nsrecord", h_nsrecord, 3, 3},
{NULL, "dialer", h_dialer, 2, 2},
{NULL, "system", h_system, 2, 2},
{NULL, "pidfile", h_pidfile, 2, 2},
{NULL, "monitor", h_monitor, 2, 2},
{NULL, "parent", h_parent, 5, 0},
{NULL, "allow", h_ace, 1, 0},
{NULL, "deny", h_ace, 1, 0},
{NULL, "redirect", h_ace, 3, 0},
{NULL, "bandlimin", h_ace, 2, 0},
{NULL, "bandlimout", h_ace, 2, 0},
{NULL, "nobandlimin", h_ace, 1, 0},
{NULL, "nobandlimout", h_ace, 1, 0},
{NULL, "countin", h_ace, 4, 0},
{NULL, "nocountin", h_ace, 1, 0},
{NULL, "countout", h_ace, 4, 0},
{NULL, "nocountout", h_ace, 1, 0},
{NULL, "countall", h_ace, 4, 0},
{NULL, "nocountall", h_ace, 1, 0},
{NULL, "connlim", h_ace, 4, 0},
{NULL, "noconnlim", h_ace, 1, 0},
{NULL, "plugin", h_plugin, 3, 0},
{NULL, "logdump", h_logdump, 2, 3},
{NULL, "filtermaxsize", h_filtermaxsize, 2, 2},
{NULL, "nolog", h_nolog, 1, 1},
{NULL, "weight", h_nolog, 2, 2},
{NULL, "authcache", h_authcache, 2, 4},
{NULL, "smtpp", h_proxy, 1, 0},
{NULL, "delimchar",h_delimchar, 2, 2},
{NULL, "authnserver", h_authnserver, 2, 2},
{NULL, "stacksize", h_stacksize, 2, 2},
{NULL, "force", h_force, 1, 1},
{NULL, "noforce", h_noforce, 1, 1},
{NULL, "parentretries", h_parentretries, 2, 2},
{NULL, "auto", h_proxy, 1, 0},
{NULL, "backlog", h_backlog, 2, 2},
{NULL, "tlspr", h_proxy, 1, 0},
{NULL, "maxseg", h_maxseg, 2, 2},
#ifndef NORADIUS
{NULL, "radius", h_radius, 3, 0},
#endif
{NULL, "", h_noop, 1, 0}
#ifndef _WIN32
{NULL, "setuid", h_setuid, 2, 2},
{NULL, "setgid", h_setgid, 2, 2},
{NULL, "chroot", h_chroot, 2, 4},
#endif
{NULL, "", h_noop, 1, 0}
};
struct commands commandhandlers[]={
{commandhandlers+1, "", h_noop, 1, 0},
{commandhandlers+2, "proxy", h_proxy, 1, 0},
{commandhandlers+3, "pop3p", h_proxy, 1, 0},
{commandhandlers+4, "ftppr", h_proxy, 1, 0},
{commandhandlers+5, "socks", h_proxy, 1, 0},
{commandhandlers+6, "tcppm", h_proxy, 4, 0},
{commandhandlers+7, "udppm", h_proxy, 4, 0},
{commandhandlers+8, "admin", h_proxy, 1, 0},
{commandhandlers+9, "dnspr", h_proxy, 1, 0},
{commandhandlers+10, "internal", h_internal, 2, 2},
{commandhandlers+11, "external", h_external, 2, 2},
{commandhandlers+12, "log", h_log, 1, 0},
{commandhandlers+13, "service", h_service, 1, 1},
{commandhandlers+14, "daemon", h_daemon, 1, 1},
{commandhandlers+15, "config", h_config, 2, 2},
{commandhandlers+16, "include", h_include, 2, 2},
{commandhandlers+17, "archiver", h_archiver, 3, 0},
{commandhandlers+18, "counter", h_counter, 2, 4},
{commandhandlers+19, "rotate", h_rotate, 2, 2},
{commandhandlers+20, "logformat", h_logformat, 2, 2},
{commandhandlers+21, "timeouts", h_timeouts, 2, 0},
{commandhandlers+22, "auth", h_auth, 2, 0},
{commandhandlers+23, "users", h_users, 1, 0},
{commandhandlers+24, "maxconn", h_maxconn, 2, 2},
{commandhandlers+25, "flush", h_flush, 1, 1},
{commandhandlers+26, "nserver", h_nserver, 2, 2},
{commandhandlers+27, "fakeresolve", h_fakeresolve, 1, 1},
{commandhandlers+28, "nscache", h_nscache, 2, 2},
{commandhandlers+29, "nscache6", h_nscache6, 2, 2},
{commandhandlers+30, "nsrecord", h_nsrecord, 3, 3},
{commandhandlers+31, "dialer", h_dialer, 2, 2},
{commandhandlers+32, "system", h_system, 2, 2},
{commandhandlers+33, "pidfile", h_pidfile, 2, 2},
{commandhandlers+34, "monitor", h_monitor, 2, 2},
{commandhandlers+35, "parent", h_parent, 5, 0},
{commandhandlers+36, "allow", h_ace, 1, 0},
{commandhandlers+37, "deny", h_ace, 1, 0},
{commandhandlers+38, "redirect", h_ace, 3, 0},
{commandhandlers+39, "bandlimin", h_ace, 2, 0},
{commandhandlers+40, "bandlimout", h_ace, 2, 0},
{commandhandlers+41, "nobandlimin", h_ace, 1, 0},
{commandhandlers+42, "nobandlimout", h_ace, 1, 0},
{commandhandlers+43, "countin", h_ace, 4, 0},
{commandhandlers+44, "nocountin", h_ace, 1, 0},
{commandhandlers+45, "countout", h_ace, 4, 0},
{commandhandlers+46, "nocountout", h_ace, 1, 0},
{commandhandlers+47, "countall", h_ace, 4, 0},
{commandhandlers+48, "nocountall", h_ace, 1, 0},
{commandhandlers+49, "connlim", h_ace, 4, 0},
{commandhandlers+50, "noconnlim", h_ace, 1, 0},
{commandhandlers+51, "plugin", h_plugin, 3, 0},
{commandhandlers+52, "logdump", h_logdump, 2, 3},
{commandhandlers+53, "filtermaxsize", h_filtermaxsize, 2, 2},
{commandhandlers+54, "nolog", h_nolog, 1, 1},
{commandhandlers+55, "weight", h_nolog, 2, 2},
{commandhandlers+56, "authcache", h_authcache, 2, 4},
{commandhandlers+57, "smtpp", h_proxy, 1, 0},
{commandhandlers+58, "delimchar",h_delimchar, 2, 2},
{commandhandlers+59, "authnserver", h_authnserver, 2, 2},
{commandhandlers+60, "stacksize", h_stacksize, 2, 2},
{commandhandlers+61, "force", h_force, 1, 1},
{commandhandlers+62, "noforce", h_noforce, 1, 1},
{commandhandlers+63, "parentretries", h_parentretries, 2, 2},
{commandhandlers+64, "auto", h_proxy, 1, 0},
{commandhandlers+65, "backlog", h_backlog, 2, 2},
{commandhandlers+66, "tlspr", h_proxy, 1, 0},
{commandhandlers+67, "maxseg", h_maxseg, 2, 2},
#ifndef NORADIUS
{commandhandlers+68, "radius", h_radius, 3, 0},
#endif
{specificcommands, "", h_noop, 1, 0}
};
void initcommands(void){
static int initialized = 0;
unsigned i;
if(initialized) return;
initialized = 1;
for(i = 0; i + 1 < sizeof(commandhandlers)/sizeof(commandhandlers[0]); i++)
commandhandlers[i].next = commandhandlers + i + 1;
}
int parsestr (unsigned char *str, unsigned char **argm, int nitems, unsigned char ** buff, int *inbuf, int *bufsize){
#define buf (*buff)

View File

@ -523,7 +523,7 @@ static void * ef_server_next(struct node * node){
static void * ef_server_type(struct node * node){
int service = ((struct srvparam *)node->value) -> service;
return (service>=0 && service < 15)? (void *)conf.stringtable[SERVICES + service] : (void *)"unknown";
return (service>=0 && service < MAX_SERVICE)? (void *)conf.stringtable[SERVICES + service] : (void *)"unknown";
}
static void * ef_server_child(struct node * node){
@ -682,7 +682,7 @@ static void * ef_client_next(struct node * node){
static void * ef_client_type(struct node * node){
int service = ((struct clientparam *)node->value) -> service;
return (service>=0 && service < 15)? (void *)conf.stringtable[SERVICES + service] : (void *)"unknown";
return (service>=0 && service < MAX_SERVICE)? (void *)conf.stringtable[SERVICES + service] : (void *)"unknown";
}
static void * ef_client_operation(struct node * node){

View File

@ -25,6 +25,7 @@ void * dnsprchild(struct clientparam* param) {
SASIZETYPE size;
int res, i;
int len;
int semlocked = 1;
unsigned type=0;
uint32_t ttl;
unsigned char addr[16];
@ -38,10 +39,13 @@ void * dnsprchild(struct clientparam* param) {
RETURN (21);
}
buf = bbuf+2;
size = sizeof(param->sincr);
i = param->srv->so._recvfrom(param->sostate, param->srv->srvsock, (char *)buf, BUFSIZE, 0, (struct sockaddr *)&param->sincr, &size);
size = sizeof(param->sinsl);
getsockname(param->srv->srvsock, (struct sockaddr *)&param->sincl, &size);
i = param->srv->udplen;
if(i > BUFSIZE) i = BUFSIZE;
memcpy(buf, param->srv->udpbuf, i);
_3proxy_sem_unlock(udpinit);
semlocked = 0;
#ifdef _WIN32
if((param->clisock=param->srv->so._socket(param->sostate, AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {
RETURN(818);
@ -82,7 +86,19 @@ void * dnsprchild(struct clientparam* param) {
*s2 = (len - (int)(s2 - buf)) - 1;
type = ((unsigned)buf[len+1])*256 + (unsigned)buf[len+2];
if((type==0x01 || type==0x1c) && !param->srv->s_option){
if(type==0x01 && param->srv->fakeip){
ip = 1;
ttl = 3600;
*(uint32_t *)addr = param->srv->fakeip;
}
#ifndef NOIPV6
else if(type==0x1c && *(uint32_t *)param->srv->fakeip6){
ip = 1;
ttl = 3600;
memcpy(addr, param->srv->fakeip6, 16);
}
#endif
else if((type==0x01 || type==0x1c) && !param->srv->s_option){
ip = udpresolve((type==0x1c)?AF_INET6:AF_INET, (unsigned char *)host, addr, &ttl, param, 0);
}
@ -191,6 +207,7 @@ void * dnsprchild(struct clientparam* param) {
CLEANRET:
if(semlocked) _3proxy_sem_unlock(udpinit);
if(param->res!=813){
sprintf((char *)buf, "%04x/%s/",
(unsigned)type,

255
src/imapp.c Normal file
View File

@ -0,0 +1,255 @@
/*
3APA3A simplest proxy server
(c) 2002-2026 by Vladimir Dubrovin <vlad@3proxy.org>
please read License Agreement
*/
#include "proxy.h"
#define RETURN(xxx) { param->res = xxx; goto CLEANRET; }
#define CL_LOGINCMD 0
#define CL_PLAIN 1
#define CL_LOGIN 2
#define CAP_PLAIN 1
#define CAP_LOGIN 2
#ifdef WITHMAIN
#define NOSTARTTLS 1
#else
#define NOSTARTTLS param->srv->nostarttls
#endif
void * imappchild(struct clientparam* param) {
int i=0, res, method=CL_LOGINCMD, caps=0;
unsigned char buf[2048];
unsigned char srvbuf[1024];
unsigned char ibuf[2048];
unsigned char tag[64];
unsigned char ub[320];
unsigned char pb[320];
unsigned char *se, *cmd, *user, *pass, *p1, *p2;
*tag = 0;
i = sprintf((char *)buf, "* OK [CAPABILITY IMAP4rev1%s AUTH=PLAIN AUTH=LOGIN] IMAP4rev1 Proxy Ready\r\n", NOSTARTTLS?"":" STARTTLS");
if(socksend(param, param->clisock, buf, i, conf.timeouts[STRING_S])!=i) {RETURN (691);}
for(;;){
i = sockgetlinebuf(param, CLIENT, buf, sizeof(buf) - 10, '\n', conf.timeouts[STRING_S]);
if(i < 4) {RETURN(692);}
buf[i] = 0;
if ((se=(unsigned char *)strchr((char *)buf, '\r'))) *se = 0;
if (!(se=(unsigned char *)strchr((char *)buf, ' ')) || (se - buf) >= (int)(sizeof(tag) - 1)) {RETURN(692);}
memcpy(tag, buf, se - buf);
tag[se - buf] = 0;
cmd = se + 1;
if(!strncasecmp((char *)cmd, "LOGOUT", 6)){
socksend(param, param->clisock, (unsigned char *)"* BYE\r\n", 7, conf.timeouts[STRING_S]);
sprintf((char *)buf, "%.60s OK LOGOUT completed\r\n", (char *)tag);
socksend(param, param->clisock, buf, (int)strlen((char *)buf), conf.timeouts[STRING_S]);
RETURN(0);
}
if(!strncasecmp((char *)cmd, "CAPABILITY", 10)){
i = sprintf((char *)buf, "* CAPABILITY IMAP4rev1%s AUTH=PLAIN AUTH=LOGIN\r\n", NOSTARTTLS?"":" STARTTLS");
socksend(param, param->clisock, buf, i, conf.timeouts[STRING_S]);
sprintf((char *)buf, "%.60s OK CAPABILITY completed\r\n", (char *)tag);
socksend(param, param->clisock, buf, (int)strlen((char *)buf), conf.timeouts[STRING_S]);
continue;
}
#ifndef WITHMAIN
if(!strncasecmp((char *)cmd, "STARTTLS", 8) && !param->srv->nostarttls){
sprintf((char *)buf, "%.60s OK Begin TLS negotiation\r\n", (char *)tag);
if(socksend(param, param->clisock, buf, (int)strlen((char *)buf), conf.timeouts[STRING_S]) <= 0) {RETURN(698);}
param->clientstarttls = S_IMAPP;
if(!param->srv->targetport) param->srv->targetport = htons(143);
return tlsprchild(param);
}
#endif
if(!strncasecmp((char *)cmd, "LOGIN ", 6)){
user = cmd + 6;
if(*user == '"') {
user++;
if (!(se=(unsigned char *)strchr((char *)user, '"'))) {RETURN(693);}
*se = 0;
pass = se + 1;
if(*pass == ' ') pass++;
}
else {
if (!(se=(unsigned char *)strchr((char *)user, ' '))) {RETURN(693);}
*se = 0;
pass = se + 1;
}
if(strlen((char *)user) >= sizeof(ub) || strlen((char *)pass) >= sizeof(pb)) {RETURN(693);}
strcpy((char *)ub, (char *)user);
strcpy((char *)pb, (char *)pass);
break;
}
if(!strncasecmp((char *)cmd, "AUTHENTICATE PLAIN", 18)){
method = CL_PLAIN;
se = cmd + 18;
if(*se == ' ') se++; else se = NULL;
if(!se || !*se){
if(socksend(param, param->clisock, (unsigned char *)"+ \r\n", 4, conf.timeouts[STRING_S])!=4) {RETURN(698);}
i = sockgetlinebuf(param, CLIENT, buf, sizeof(buf) - 10, '\n', conf.timeouts[STRING_S]);
if(i < 1) {RETURN(698);}
buf[i] = 0;
if ((se=(unsigned char *)strchr((char *)buf, '\r'))) *se = 0;
se = buf;
}
i = de64(se, ibuf, (int)sizeof(ibuf) - 1);
if(i < 3) {RETURN(693);}
ibuf[i] = 0;
p1 = (unsigned char *)memchr(ibuf, 0, i);
if(!p1 || p1 == ibuf + i - 1) {RETURN(693);}
p2 = (unsigned char *)memchr(p1 + 1, 0, i - (int)(p1 + 1 - ibuf));
if(p2){
user = p1 + 1;
pass = p2 + 1;
}
else {
user = ibuf;
pass = p1 + 1;
}
if(strlen((char *)user) >= sizeof(ub) || strlen((char *)pass) >= sizeof(pb)) {RETURN(693);}
strcpy((char *)ub, (char *)user);
strcpy((char *)pb, (char *)pass);
break;
}
if(!strncasecmp((char *)cmd, "AUTHENTICATE LOGIN", 18)){
method = CL_LOGIN;
se = cmd + 18;
if(*se == ' ') se++; else se = NULL;
if(se && *se){
i = de64(se, ub, (int)sizeof(ub) - 1);
if(i < 0) {RETURN(693);}
ub[i] = 0;
}
else {
if(socksend(param, param->clisock, (unsigned char *)"+ VXNlcm5hbWU6\r\n", 16, conf.timeouts[STRING_S])!=16) {RETURN(698);}
i = sockgetlinebuf(param, CLIENT, buf, sizeof(buf) - 10, '\n', conf.timeouts[STRING_S]);
if(i < 1) {RETURN(698);}
buf[i] = 0;
if ((se=(unsigned char *)strchr((char *)buf, '\r'))) *se = 0;
i = de64(buf, ub, (int)sizeof(ub) - 1);
if(i < 0) {RETURN(693);}
ub[i] = 0;
}
if(socksend(param, param->clisock, (unsigned char *)"+ UGFzc3dvcmQ6\r\n", 16, conf.timeouts[STRING_S])!=16) {RETURN(698);}
i = sockgetlinebuf(param, CLIENT, buf, sizeof(buf) - 10, '\n', conf.timeouts[STRING_S]);
if(i < 1) {RETURN(698);}
buf[i] = 0;
if ((se=(unsigned char *)strchr((char *)buf, '\r'))) *se = 0;
i = de64(buf, pb, (int)sizeof(pb) - 1);
if(i < 0) {RETURN(693);}
pb[i] = 0;
break;
}
sprintf((char *)buf, "%.60s BAD need LOGIN first\r\n", (char *)tag);
socksend(param, param->clisock, buf, (int)strlen((char *)buf), conf.timeouts[STRING_S]);
}
if(parseconnusername((char *)ub, param, 0, 143)){RETURN(694);}
if(*pb && !param->password) param->password = (unsigned char *)strdup((char *)pb);
param->operation = CONNECT;
res = (*param->srv->authfunc)(param);
if(res) {RETURN(res);}
i = sockgetlinebuf(param, SERVER, srvbuf, sizeof(srvbuf) - 1, '\n', conf.timeouts[STRING_L]);
if( i < 4 ) {RETURN(695);}
srvbuf[i] = 0;
if(strncasecmp((char *)srvbuf, "* OK", 4)||strstr((char *)srvbuf, "IMAP4rev1 Proxy Ready")){RETURN(696);}
if((se = (unsigned char *)strstr((char *)srvbuf, "[CAPABILITY "))){
if(hascap(se, "AUTH=PLAIN")) caps |= CAP_PLAIN;
if(hascap(se, "AUTH=LOGIN")) caps |= CAP_LOGIN;
}
else {
if(socksend(param, param->remsock, (unsigned char *)"zz CAPABILITY\r\n", 15, conf.timeouts[STRING_S])!=15) {RETURN(697);}
for(;;){
i = sockgetlinebuf(param, SERVER, srvbuf, sizeof(srvbuf) - 1, '\n', conf.timeouts[STRING_L]);
if(i < 3) {RETURN(697);}
srvbuf[i] = 0;
if(!strncasecmp((char *)srvbuf, "* CAPABILITY", 12)){
if(hascap(srvbuf, "AUTH=PLAIN")) caps |= CAP_PLAIN;
if(hascap(srvbuf, "AUTH=LOGIN")) caps |= CAP_LOGIN;
continue;
}
if(!strncasecmp((char *)srvbuf, "zz ", 3)) break;
}
}
if(method == CL_PLAIN && !(caps & CAP_PLAIN)) method = (caps & CAP_LOGIN)? CL_LOGIN : CL_LOGINCMD;
else if(method == CL_LOGIN && !(caps & CAP_LOGIN)) method = (caps & CAP_PLAIN)? CL_PLAIN : CL_LOGINCMD;
else if(method == CL_LOGINCMD && caps) method = (caps & CAP_PLAIN)? CL_PLAIN : CL_LOGIN;
if(method == CL_PLAIN){
i = (int)strlen((char *)param->extusername);
res = (int)strlen((char *)pb);
if(((i + res + 4) / 3) * 4 + 1 > (int)sizeof(srvbuf)) {RETURN(693);}
ibuf[0] = 0;
memcpy(ibuf + 1, param->extusername, i);
ibuf[i + 1] = 0;
memcpy(ibuf + i + 2, pb, res);
en64(ibuf, srvbuf, i + res + 2);
if( socksend(param, param->remsock, tag, (int)strlen((char *)tag), conf.timeouts[STRING_S]) <= 0 ||
socksend(param, param->remsock, (unsigned char *)" AUTHENTICATE PLAIN ", 20, conf.timeouts[STRING_S])!= 20 ||
socksend(param, param->remsock, srvbuf, (int)strlen((char *)srvbuf), conf.timeouts[STRING_S]) <= 0 ||
socksend(param, param->remsock, (unsigned char *)"\r\n", 2, conf.timeouts[STRING_S])!=2)
{RETURN(699);}
}
else if(method == CL_LOGIN){
if( socksend(param, param->remsock, tag, (int)strlen((char *)tag), conf.timeouts[STRING_S]) <= 0 ||
socksend(param, param->remsock, (unsigned char *)" AUTHENTICATE LOGIN\r\n", 21, conf.timeouts[STRING_S])!= 21)
{RETURN(699);}
i = sockgetlinebuf(param, SERVER, srvbuf, sizeof(srvbuf) - 1, '\n', conf.timeouts[STRING_L]);
if(i < 1 || *srvbuf != '+') {RETURN(699);}
if(((int)strlen((char *)param->extusername) + 2) / 3 * 4 + 1 > (int)sizeof(ibuf) - 3) {RETURN(693);}
en64(param->extusername, ibuf, (int)strlen((char *)param->extusername));
if( socksend(param, param->remsock, ibuf, (int)strlen((char *)ibuf), conf.timeouts[STRING_S]) <= 0 ||
socksend(param, param->remsock, (unsigned char *)"\r\n", 2, conf.timeouts[STRING_S])!=2)
{RETURN(699);}
i = sockgetlinebuf(param, SERVER, srvbuf, sizeof(srvbuf) - 1, '\n', conf.timeouts[STRING_L]);
if(i < 1 || *srvbuf != '+') {RETURN(699);}
if(((int)strlen((char *)pb) + 2) / 3 * 4 + 1 > (int)sizeof(ibuf) - 3) {RETURN(693);}
en64(pb, ibuf, (int)strlen((char *)pb));
if( socksend(param, param->remsock, ibuf, (int)strlen((char *)ibuf), conf.timeouts[STRING_S]) <= 0 ||
socksend(param, param->remsock, (unsigned char *)"\r\n", 2, conf.timeouts[STRING_S])!=2)
{RETURN(699);}
}
else {
if( socksend(param, param->remsock, tag, (int)strlen((char *)tag), conf.timeouts[STRING_S]) <= 0 ||
socksend(param, param->remsock, (unsigned char *)" LOGIN ", 7, conf.timeouts[STRING_S])!= 7 ||
socksend(param, param->remsock, param->extusername, (int)strlen((char *)param->extusername), conf.timeouts[STRING_S]) <= 0 ||
socksend(param, param->remsock, (unsigned char *)" ", 1, conf.timeouts[STRING_S])!= 1 ||
socksend(param, param->remsock, pb, (int)strlen((char *)pb), conf.timeouts[STRING_S]) <= 0 ||
socksend(param, param->remsock, (unsigned char *)"\r\n", 2, conf.timeouts[STRING_S])!=2)
{RETURN(699);}
}
param->statscli64 += (uint64_t)(strlen((char *)tag) + strlen((char *)param->extusername) + strlen((char *)pb) + 11);
param->nwrites++;
RETURN (mapsocket(param, 180));
CLEANRET:
if(param->hostname&&param->extusername) {
sprintf((char *)buf, "%.128s@%.128s%c%hu", param->extusername, param->hostname, (*SAPORT(&param->sinsr)==143)?0:':', ntohs(*SAPORT(&param->sinsr)));
dolog(param, buf);
}
else dolog(param, NULL);
if(param->clisock != INVALID_SOCKET) {
if ((param->res > 0 && param->res < 100) || (param->res > 691 && param->res <700)) {
sprintf((char *)buf, "%.60s NO proxy error\r\n", *tag? (char *)tag : "*");
socksend(param, param->clisock, buf, (int)strlen((char *)buf),conf.timeouts[STRING_S]);
}
}
freeparam(param);
return (NULL);
}
#ifdef WITHMAIN
struct proxydef childdef = {
imappchild,
143,
0,
S_IMAPP,
" -hdefault_host[:port] - use this host and port as default if no host specified\n -x - disable STARTTLS\n"
};
#include "proxymain.c"
#endif

View File

@ -71,6 +71,7 @@ struct symbol symbols[] = {
{symbols+46, "make_ace", (void *) make_ace},
{symbols+47, "freeacl", (void *) freeacl},
{symbols+48, "handleredirect", (void *) handleredirect},
{symbols+49, "imapp", (void *) imappchild},
{NULL, "", NULL}
};

View File

@ -10,6 +10,12 @@
#define RETURN(xxx) { param->res = xxx; goto CLEANRET; }
#ifdef WITHMAIN
#define NOSTARTTLS 1
#else
#define NOSTARTTLS param->srv->nostarttls
#endif
void * pop3pchild(struct clientparam* param) {
int i=0, res;
unsigned char buf[320];
@ -22,6 +28,19 @@ void * pop3pchild(struct clientparam* param) {
socksend(param, param->clisock, (unsigned char *)"+OK\r\n", 5,conf.timeouts[STRING_S]);
RETURN(0);
}
if(!strncasecmp((char *)buf, "CAPA", 4) && !NOSTARTTLS){
socksend(param, param->clisock, (unsigned char *)"+OK Capability list follows\r\nSTLS\r\n.\r\n", 38, conf.timeouts[STRING_S]);
i = sockgetlinebuf(param, CLIENT, buf, sizeof(buf) - 10, '\n', conf.timeouts[STRING_S]);
continue;
}
#ifndef WITHMAIN
if(!strncasecmp((char *)buf, "STLS", 4) && !param->srv->nostarttls){
if(socksend(param, param->clisock, (unsigned char *)"+OK Begin TLS negotiation\r\n", 27, conf.timeouts[STRING_S])!=27) {RETURN(623);}
param->clientstarttls = S_POP3P;
if(!param->srv->targetport) param->srv->targetport = htons(110);
return tlsprchild(param);
}
#endif
socksend(param, param->clisock, (unsigned char *)"-ERR need USER first\r\n", 22, conf.timeouts[STRING_S]);
i = sockgetlinebuf(param, CLIENT, buf, sizeof(buf) - 10, '\n', conf.timeouts[STRING_S]);
}
@ -65,7 +84,7 @@ struct proxydef childdef = {
110,
0,
S_POP3P,
" -hdefault_host[:port] - use this host and port as default if no host specified\n"
" -hdefault_host[:port] - use this host and port as default if no host specified\n -x - disable STARTTLS\n"
};
#include "proxymain.c"

View File

@ -188,6 +188,8 @@ unsigned long sockfillbuffcli(struct clientparam * param, unsigned long size, in
unsigned long sockfillbuffsrv(struct clientparam * param, unsigned long size, int timeosec);
int sockgetlinebuf(struct clientparam * param, DIRECTION which, unsigned char * buf, int bufsize, int delim, int to);
int getmultiline(struct clientparam * param, DIRECTION which, unsigned char * buf, int bufsize, const char *cap, int *found);
int hascap(const unsigned char *line, const char *cap);
@ -312,6 +314,7 @@ void srvinit2(struct srvparam * srv, struct clientparam *param);
void srvfree(struct srvparam * srv);
unsigned char * dologname (unsigned char *buf, unsigned char *name, const unsigned char *ext, ROTATION lt, time_t t);
int readconfig(FILE * fp);
void initcommands(void);
int connectwithpoll(struct clientparam *param, SOCKET sock, struct sockaddr *sa, SASIZETYPE size, int to);
@ -325,6 +328,7 @@ extern char *copyright;
void * dnsprchild(struct clientparam * param);
void * pop3pchild(struct clientparam * param);
void * imappchild(struct clientparam * param);
void * smtppchild(struct clientparam * param);
void * proxychild(struct clientparam * param);
void * sockschild(struct clientparam * param);

View File

@ -528,6 +528,27 @@ int MODULEMAINFUNC (int argc, char** argv){
srv.needuser = 0;
if(*(argv[i] + 2)) srv.needuser = atoi(argv[i] + 2);
break;
case 'x':
srv.nostarttls = 1;
break;
case 'X':
if(!strncasecmp(argv[i]+2, "imap", 4)) srv.srvstarttls = S_IMAPP;
else if(!strncasecmp(argv[i]+2, "pop3", 4)) srv.srvstarttls = S_POP3P;
else if(!strncasecmp(argv[i]+2, "smtp", 4)) srv.srvstarttls = S_SMTPP;
else error = 1;
break;
case 'F':
{
PROXYSOCKADDRTYPE fsa;
memset(&fsa, 0, sizeof(fsa));
if(!getip46(46, (unsigned char *)argv[i]+2, (struct sockaddr *)&fsa)) error = 1;
else if(*SAFAMILY(&fsa) == AF_INET) srv.fakeip = *(uint32_t *)SAADDR(&fsa);
#ifndef NOIPV6
else if(*SAFAMILY(&fsa) == AF_INET6) memcpy(srv.fakeip6, SAADDR(&fsa), 16);
#endif
else error = 1;
}
break;
case 'T':
srv.transparent = 1;
break;

View File

@ -47,6 +47,7 @@ int clientnegotiate(struct chain * redir, struct clientparam * param, struct soc
switch(redir->type){
case R_TCP:
case R_HTTP:
case R_IMAP:
return 0;
case R_CONNECT:
case R_CONNECTP:

View File

@ -10,11 +10,23 @@
#define RETURN(xxx) { param->res = xxx; goto CLEANRET; }
#ifdef WITHMAIN
#define NOSTARTTLS 1
#else
#define NOSTARTTLS param->srv->nostarttls
#endif
char ehlo[] = "250-Proxy\r\n"
"250-AUTH PLAIN LOGIN\r\n"
"250-8BITMIME\r\n"
"250 DSN\r\n";
char ehlotls[] = "250-Proxy\r\n"
"250-AUTH PLAIN LOGIN\r\n"
"250-8BITMIME\r\n"
"250-STARTTLS\r\n"
"250 DSN\r\n";
int readreply (struct clientparam* param) {
unsigned char * buf;
int res, i, bufsize = 640;
@ -112,8 +124,17 @@ void * smtppchild(struct clientparam* param) {
socksend(param, param->clisock, (unsigned char *)"250 Proxy\r\n", 11,conf.timeouts[STRING_S]);
}
else if(!strncasecmp((char *)buf, "EHLO ", 5)){
socksend(param, param->clisock, (unsigned char *)ehlo, sizeof(ehlo) - 1,conf.timeouts[STRING_S]);
if(!NOSTARTTLS) socksend(param, param->clisock, (unsigned char *)ehlotls, sizeof(ehlotls) - 1,conf.timeouts[STRING_S]);
else socksend(param, param->clisock, (unsigned char *)ehlo, sizeof(ehlo) - 1,conf.timeouts[STRING_S]);
}
#ifndef WITHMAIN
else if(!strncasecmp((char *)buf, "STARTTLS", 8) && !param->srv->nostarttls){
if(socksend(param, param->clisock, (unsigned char *)"220 2.0.0 Ready to start TLS\r\n", 30, conf.timeouts[STRING_S])!=30) {RETURN(673);}
param->clientstarttls = S_SMTPP;
if(!param->srv->targetport) param->srv->targetport = htons(587);
return tlsprchild(param);
}
#endif
else if(!param->hostname) socksend(param, param->clisock, (unsigned char *)"571 need AUTH first\r\n", 22, conf.timeouts[STRING_S]);
else {
login = -1;
@ -132,7 +153,7 @@ void * smtppchild(struct clientparam* param) {
i = de64(buf,username,255);
if(i < 1) {RETURN(664);}
username[i] = 0;
parseconnusername((char *)username, param, 0, 25);
parseconnusername((char *)username, param, 0, 587);
socksend(param, param->clisock, (unsigned char *)"334 UGFzc3dvcmQ6\r\n", 18,conf.timeouts[STRING_S]);
i = sockgetlinebuf(param, CLIENT, buf, sizeof(buf) - 10, '\n', conf.timeouts[STRING_S]);
if(i < 2) {RETURN(665);}
@ -157,7 +178,7 @@ void * smtppchild(struct clientparam* param) {
}
if(i < 3 || *username) {RETURN(668);}
username[i] = 0;
parseconnusername((char *)username+1, param, 0, 25);
parseconnusername((char *)username+1, param, 0, 587);
res = (int)strlen((char *)username+1) + 2;
if(res < i){
if(param->extpassword) free(param->extpassword);
@ -180,9 +201,7 @@ void * smtppchild(struct clientparam* param) {
param->operation = CONNECT;
res = (*param->srv->authfunc)(param);
if(res) {RETURN(res);}
do {
i = sockgetlinebuf(param, SERVER, buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L]);
} while (i > 3 && buf[3] == '-');
i = getmultiline(param, SERVER, buf, sizeof(buf) - 1, NULL, NULL);
if( i < 3 ) {RETURN(671);}
buf[i] = 0;
if(strncasecmp((char *)buf, "220", 3)||!strncasecmp((char *)buf+4, "PROXY", 5)){RETURN(672);}
@ -292,7 +311,7 @@ void * smtppchild(struct clientparam* param) {
CLEANRET:
if(param->hostname&&param->extusername) {
sprintf((char *)buf, "%.128s@%.128s%c%hu", param->extusername, param->hostname, *SAPORT(&param->sinsr)==25?0:':',ntohs(*SAPORT(&param->sinsr)));
sprintf((char *)buf, "%.128s@%.128s%c%hu", param->extusername, param->hostname, *SAPORT(&param->sinsr)==587?0:':',ntohs(*SAPORT(&param->sinsr)));
dolog(param, buf);
}
else dolog(param, NULL);
@ -307,10 +326,10 @@ CLEANRET:
#ifdef WITHMAIN
struct proxydef childdef = {
smtppchild,
25,
587,
0,
S_SMTPP,
" -hdefault_host[:port] - use this host and port as default if no host specified\n"
" -hdefault_host[:port] - use this host and port as default if no host specified\n -x - disable STARTTLS\n"
};
#include "proxymain.c"

View File

@ -30,8 +30,8 @@ unsigned char * strings[] = {
/* 17 */ (unsigned char *)"SMTPP",
/* 18 */ (unsigned char *)"AUTO",
/* 19 */ (unsigned char *)"TLSPR",
/* 20 */ (unsigned char *)"ZOMBIE",
/* 21 */ NULL,
/* 20 */ (unsigned char *)"IMAPP",
/* 21 */ (unsigned char *)"ZOMBIE",
/* 22 */ NULL,
/* 23 */ NULL,
/* 24 */ NULL,

View File

@ -208,6 +208,7 @@ typedef enum {
S_SMTPP,
S_AUTO,
S_TLSPR,
S_IMAPP,
S_ZOMBIE
}PROXYSERVICE;
@ -304,7 +305,8 @@ typedef enum {
R_EXTIP,
R_TLS,
R_HA,
R_DNS
R_DNS,
R_IMAP
} REDIRTYPE;
struct redirdesc {
@ -535,6 +537,10 @@ struct srvparam {
int gracetraf, gracenum, gracedelay;
int requirecert;
int haproxy;
int nostarttls;
PROXYSERVICE srvstarttls;
uint32_t fakeip;
unsigned char fakeip6[16];
#ifdef WITHSPLICE
int usesplice;
#endif
@ -594,6 +600,8 @@ struct clientparam {
PROXYSERVICE service;
PROXYSERVICE clientstarttls;
SOCKET clisock,
remsock,
ctrlsock,

View File

@ -37,6 +37,176 @@ int readtls(struct clientparam *param, int direction, unsigned char *buf, int bu
#define SNILEN (256)
#define PROTOLEN (32)
int srvstarttls(struct clientparam *param, PROXYSERVICE proto){
unsigned char buf[1024];
int i, found = 0;
switch(proto){
case S_IMAPP:
i = sockgetlinebuf(param, SERVER, buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L]);
if(i < 4) return 1;
buf[i] = 0;
if(strncasecmp((char *)buf, "* OK", 4)) return 1;
found = hascap(buf, "STARTTLS");
if(!found){
if(socksend(param, param->remsock, (unsigned char *)"zz CAPABILITY\r\n", 15, conf.timeouts[STRING_S])!=15) return 2;
for(;;){
i = sockgetlinebuf(param, SERVER, buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L]);
if(i < 3) return 2;
buf[i] = 0;
if(!strncasecmp((char *)buf, "* CAPABILITY", 12) && hascap(buf, "STARTTLS")) found = 1;
if(!strncasecmp((char *)buf, "zz ", 3)) break;
}
if(!found) return 3;
}
if(socksend(param, param->remsock, (unsigned char *)"zz STARTTLS\r\n", 13, conf.timeouts[STRING_S])!=13) return 2;
i = sockgetlinebuf(param, SERVER, buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L]);
if(i < 5) return 2;
buf[i] = 0;
if(strncasecmp((char *)buf, "zz OK", 5)) return 3;
break;
case S_POP3P:
i = sockgetlinebuf(param, SERVER, buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L]);
if(i < 3) return 1;
buf[i] = 0;
if(strncasecmp((char *)buf, "+OK", 3)) return 1;
if(socksend(param, param->remsock, (unsigned char *)"CAPA\r\n", 6, conf.timeouts[STRING_S])!=6) return 2;
for(;;){
i = sockgetlinebuf(param, SERVER, buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L]);
if(i < 1) return 2;
buf[i] = 0;
if(buf[0] == '.') break;
if(!strncasecmp((char *)buf, "-ERR", 4)) return 2;
if(hascap(buf, "STLS")) found = 1;
}
if(!found) return 3;
if(socksend(param, param->remsock, (unsigned char *)"STLS\r\n", 6, conf.timeouts[STRING_S])!=6) return 2;
i = sockgetlinebuf(param, SERVER, buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L]);
if(i < 3) return 2;
buf[i] = 0;
if(strncasecmp((char *)buf, "+OK", 3)) return 3;
break;
case S_SMTPP:
i = getmultiline(param, SERVER, buf, sizeof(buf) - 1, NULL, NULL);
if(i < 3) return 1;
buf[i] = 0;
if(strncasecmp((char *)buf, "220", 3)) return 1;
i = sprintf((char *)buf, "EHLO [");
i += myinet_ntop(*SAFAMILY(&param->sinsl), SAADDR(&param->sinsl), (char *)buf+strlen((char *)buf), 64);
i += sprintf((char *)buf+strlen((char *)buf), "]\r\n");
if(socksend(param, param->remsock, buf, i, conf.timeouts[STRING_S])!= i) return 2;
i = getmultiline(param, SERVER, buf, sizeof(buf) - 1, "STARTTLS", &found);
if(i < 3) return 2;
buf[i] = 0;
if(strncasecmp((char *)buf, "250", 3)) return 2;
if(!found) return 3;
if(socksend(param, param->remsock, (unsigned char *)"STARTTLS\r\n", 10, conf.timeouts[STRING_S])!= 10) return 2;
i = sockgetlinebuf(param, SERVER, buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L]);
if(i < 3) return 2;
buf[i] = 0;
if(strncasecmp((char *)buf, "220", 3)) return 3;
break;
default:
return 1;
}
return 0;
}
uint16_t starttlsport(PROXYSERVICE proto){
switch(proto){
case S_IMAPP: return 143;
case S_POP3P: return 110;
case S_SMTPP: return 587;
default: return 443;
}
}
int clistarttls(struct clientparam *param, PROXYSERVICE proto){
unsigned char buf[1024];
unsigned char tag[64];
unsigned char *se, *cmd;
int i;
switch(proto){
case S_IMAPP:
i = sprintf((char *)buf, "* OK [CAPABILITY IMAP4rev1 STARTTLS LOGINDISABLED] IMAP4rev1 Proxy Ready\r\n");
if(socksend(param, param->clisock, buf, i, conf.timeouts[STRING_S])!=i) return 1;
for(;;){
i = sockgetlinebuf(param, CLIENT, buf, sizeof(buf) - 10, '\n', conf.timeouts[STRING_S]);
if(i < 4) return 1;
buf[i] = 0;
if ((se=(unsigned char *)strchr((char *)buf, '\r'))) *se = 0;
if (!(se=(unsigned char *)strchr((char *)buf, ' ')) || (se - buf) >= (int)(sizeof(tag) - 1)) return 1;
memcpy(tag, buf, se - buf);
tag[se - buf] = 0;
cmd = se + 1;
if(!strncasecmp((char *)cmd, "LOGOUT", 6)){
socksend(param, param->clisock, (unsigned char *)"* BYE\r\n", 7, conf.timeouts[STRING_S]);
sprintf((char *)buf, "%.60s OK LOGOUT completed\r\n", (char *)tag);
socksend(param, param->clisock, buf, (int)strlen((char *)buf), conf.timeouts[STRING_S]);
return -1;
}
if(!strncasecmp((char *)cmd, "CAPABILITY", 10)){
i = sprintf((char *)buf, "* CAPABILITY IMAP4rev1 STARTTLS LOGINDISABLED\r\n");
socksend(param, param->clisock, buf, i, conf.timeouts[STRING_S]);
sprintf((char *)buf, "%.60s OK CAPABILITY completed\r\n", (char *)tag);
socksend(param, param->clisock, buf, (int)strlen((char *)buf), conf.timeouts[STRING_S]);
continue;
}
if(!strncasecmp((char *)cmd, "STARTTLS", 8)){
sprintf((char *)buf, "%.60s OK Begin TLS negotiation\r\n", (char *)tag);
if(socksend(param, param->clisock, buf, (int)strlen((char *)buf), conf.timeouts[STRING_S]) <= 0) return 1;
return 0;
}
sprintf((char *)buf, "%.60s BAD need STARTTLS first\r\n", (char *)tag);
socksend(param, param->clisock, buf, (int)strlen((char *)buf), conf.timeouts[STRING_S]);
}
case S_POP3P:
if(socksend(param, param->clisock, (unsigned char *)"+OK Proxy\r\n", 11, conf.timeouts[STRING_S])!=11) return 1;
for(;;){
i = sockgetlinebuf(param, CLIENT, buf, sizeof(buf) - 10, '\n', conf.timeouts[STRING_S]);
if(i < 4) return 1;
if(!strncasecmp((char *)buf, "STLS", 4)){
if(socksend(param, param->clisock, (unsigned char *)"+OK Begin TLS negotiation\r\n", 27, conf.timeouts[STRING_S])!=27) return 1;
return 0;
}
if(!strncasecmp((char *)buf, "CAPA", 4)){
socksend(param, param->clisock, (unsigned char *)"+OK Capability list follows\r\nSTLS\r\n.\r\n", 38, conf.timeouts[STRING_S]);
continue;
}
if(!strncasecmp((char *)buf, "QUIT", 4)){
socksend(param, param->clisock, (unsigned char *)"+OK\r\n", 5, conf.timeouts[STRING_S]);
return -1;
}
socksend(param, param->clisock, (unsigned char *)"-ERR need STLS first\r\n", 22, conf.timeouts[STRING_S]);
}
case S_SMTPP:
if(socksend(param, param->clisock, (unsigned char *)"220 Proxy\r\n", 11, conf.timeouts[STRING_S])!=11) return 1;
for(;;){
i = sockgetlinebuf(param, CLIENT, buf, sizeof(buf) - 10, '\n', conf.timeouts[STRING_S]);
if(i < 4) return 1;
if(!strncasecmp((char *)buf, "STARTTLS", 8)){
if(socksend(param, param->clisock, (unsigned char *)"220 2.0.0 Ready to start TLS\r\n", 30, conf.timeouts[STRING_S])!=30) return 1;
return 0;
}
if(!strncasecmp((char *)buf, "EHLO ", 5)){
socksend(param, param->clisock, (unsigned char *)"250-Proxy\r\n250 STARTTLS\r\n", 24, conf.timeouts[STRING_S]);
continue;
}
if(!strncasecmp((char *)buf, "HELO ", 5)){
socksend(param, param->clisock, (unsigned char *)"250 Proxy\r\n", 11, conf.timeouts[STRING_S]);
continue;
}
if(!strncasecmp((char *)buf, "QUIT", 4)){
socksend(param, param->clisock, (unsigned char *)"221 Proxy\r\n", 11, conf.timeouts[STRING_S]);
return -1;
}
socksend(param, param->clisock, (unsigned char *)"530 5.7.0 Must issue a STARTTLS command first\r\n", 45, conf.timeouts[STRING_S]);
}
}
return 1;
}
int parsehello(int type, unsigned char *hello, unsigned len, char *sni, int * snipos, int *lv, char * proto){
unsigned offset;
@ -176,6 +346,13 @@ void * tlsprchild(struct clientparam* param) {
int lv=-1;
char proto[PROTOLEN]="-";
int snipos = 0;
PROXYSERVICE stlsproto = param->clientstarttls? param->clientstarttls : param->srv->srvstarttls;
if(!param->clientstarttls && stlsproto){
res = clistarttls(param, stlsproto);
if(res > 0) RETURN(364);
if(res < 0) RETURN(0);
}
res = tlstobufcli(param);
if(res <= 0 || param->clibuf[0] != 22){
@ -189,7 +366,7 @@ void * tlsprchild(struct clientparam* param) {
free(param->hostname);
param->hostname = NULL;
}
else if (parsehostname(sni, param, param->srv->targetport? ntohs(param->srv->targetport):443)) RETURN (100);
else if (parsehostname(sni, param, param->srv->targetport? ntohs(param->srv->targetport):starttlsport(stlsproto))) RETURN (100);
if (!param->hostname)param->hostname = (unsigned char *)strdup(sni);
if(param->srv->s_option && snipos && res > 1){
int len;
@ -220,6 +397,14 @@ void * tlsprchild(struct clientparam* param) {
return (*param->redirectfunc)(param);
}
if(stlsproto){
res = srvstarttls(param, stlsproto);
if(res){
socksend(param, param->clisock, (unsigned char *)"\x15\x03\x01\x00\x02\x02\x28", 7, conf.timeouts[STRING_S]);
RETURN(360+res);
}
}
if(param->srv->requirecert > 1){
res = tlstobufsrv(param);
if(res <= 0 || param->srvbuf[0] != 22) RETURN(340-res);