mirror of
https://github.com/3proxy/3proxy.git
synced 2026-10-30 14:45:49 +08:00
Compare commits
6 Commits
f52dc0f0b9
...
f271a57238
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f271a57238 | ||
|
|
dded867ede | ||
|
|
fad5acea9a | ||
|
|
a0ea1b3e7d | ||
|
|
5e71f7daff | ||
|
|
36ae10ad16 |
36
CHANGELOG
36
CHANGELOG
@ -1,13 +1,25 @@
|
|||||||
3proxy-1.0.0 Released August, 22 2026
|
3proxy-1.0.1 Released October, 10 2026
|
||||||
|
|
||||||
No changes in 3proxy code, this release only changes how packages are built, signed and published.
|
! Fix: crash (segmentation fault) on configuration reload (SIGUSR1) on a busy server: a closing session could still use its service after the reload had freed it; the race existed since 0.9.7, the 5 second linger added in 0.9.9 made it much more likely (#1278)
|
||||||
|
! Fix: -Di and -De (bind to interface) were not applied to SOCKSv5 UDP ASSOCIATE and BIND sockets, the FTP proxy data connection and connect back (#1277)
|
||||||
! Fix: TLS, PCRE2 and PAM support was silently left out when 3proxy was built on a system whose /bin/sh is not dash, which is every RPM based distribution and macOS; the library checks built their test program with echo and escape sequences, which only dash expands, so every check failed and the features were dropped without a diagnostic
|
! Fix: SOCKSv5 UDP ASSOCIATE over IPv6: the source address of a datagram was truncated and the reply was sent to the wrong address (#1279)
|
||||||
! Fix: rpm packages were built on Ubuntu and required glibc 2.38, libssl.so.3 and libpcre2-8, which no RPM based distribution provides, so they could not be installed anywhere; they are built against AlmaLinux 8, 9 and 10 now and carry an el8, el9 or el10 tag, covering RHEL, AlmaLinux, Rocky and CentOS Stream of the same version
|
! Fix: SOCKSv5 UDP ASSOCIATE: an access rule with host names matched any datagram sent to a literal address; the address is used as the host name now, as it is for TCP requests
|
||||||
! Fix: the rpm package depended on its own interpreter, /bin/3proxy, taken from the first line of the installed configuration file, and could not be installed on el9 or el10 because rpm resolves that dependency to /usr/bin/3proxy
|
! Fix: a request rewritten with pcre_rewrite was only logged and was sent unchanged to the server on a direct connection; the rewritten path and query are what the server receives now
|
||||||
! Fix: deb packages required glibc 2.38 and libssl3t64 and installed on Ubuntu 24.04 and newer only; they are built against Ubuntu 22.04 now and install on Ubuntu 22.04 and later as well as Debian 12 and later
|
! Fix: buffer could be insufficient for the headers the HTTP proxy adds after a pcre_rewrite had grown the request
|
||||||
+ Signed apt and dnf repositories are published at https://3proxy.org/repo/ in two channels: current, built from the master branch, and lts, built from the 0.9 branch; packages and repository metadata are both signed
|
! Fix: heap buffer overflow in pcre_rewrite: a $N reference to a group which did not match was written out as its digits, which the space allocated for the result did not count
|
||||||
+ Release binaries are published with SHA256 checksums, an OpenPGP signature and a GitHub build provenance attestation; docker images are signed and attested as well
|
! Fix: pcre_extend did nothing, the rules it appended were never consulted; the manual described an argument the command does not take
|
||||||
+ The release signing key is an RSA-4096 key published as 3proxy-release-key.asc in the repository; rpm 4.14 and earlier can not import an Ed25519 key at all, which would leave RHEL 8 and its derivatives unable to verify anything
|
! Fix: certificates generated for TLS MitM (openssl) carried no subject and authority key identifiers and were refused by strict verifiers, including macOS clients, OpenSSL with x509_strict and Python 3.13
|
||||||
+ Packages are reproducible: rebuilding a release produces byte identical deb and rpm files, every timestamp is derived from the build date recorded for the release
|
! Fix: null pointer dereference in ftppr on PASS without USER and in smtpp on a user name without a host
|
||||||
- 32-bit ARM (armhf) is published as a deb package only, Enterprise Linux has no 32-bit ARM build
|
! Fix: no service started with wolfSSL on glibc: the default thread stack was too small for wolfSSL thread-local storage, pthread_create() failed and the failure was not reported
|
||||||
|
! Fix: dnspr did not work on Windows; Windows builds answer UDP from a socket of their own again
|
||||||
|
+ Built-in HTTP server: httpsrv service with http rules to serve files (cached or with sendfile / TransmitFile), redirects, rewrites, fixed replies and proxypass to forward requests as the proxy does, so one port can serve both a site and a proxy; admin is httpsrv with the administration pages
|
||||||
|
+ Host names in access rules may be regular expressions with a pcre: (or regex:) prefix
|
||||||
|
+ transparent / notransparent commands: transparent proxying is built in (netfilter on Linux, pf on BSD, socket for divert-to and ipfw fwd), TransparentPlugin is removed and a configuration loading it keeps working
|
||||||
|
+ parent: weight may be written as a fraction (.5) or a percentage (50%); weight 0 is a fallback parent used only when every weighted parent of its group has failed; a failed parent is left out of the next attempt of the same connection
|
||||||
|
+ parent extport / intport: range of local ports for outgoing connections and for sockets facing the client (UDP ASSOCIATE, FTP data)
|
||||||
|
+ A parent given by host name is resolved for each connection when nserver is used, instead of once on configuration load
|
||||||
|
+ $$ in the configuration stands for a single dollar sign, a dollar inside quotes is ordinary text
|
||||||
|
+ OpenWrt package (procd init script, UCI configuration) and OpenWrt builds for mipsel_24kc, mips_24kc, arm_cortex-a7_neon-vfpv4 and aarch64_cortex-a53
|
||||||
|
- pop3p, imapp, smtpp and ftppr are not in a default build: build with MAILPROXY=true and FTP=true (CMake: 3PROXY_USE_MAILPROXY, 3PROXY_USE_FTP); without them the mail proxies run as tlspr negotiating STARTTLS, and ftppr refuses clients
|
||||||
|
- FTP over HTTP proxy (ftp:// URLs) is not in a default build either and has to be enabled explicitly: build with FTP=true (CMake: 3PROXY_USE_FTP), without it the HTTP proxy does not fetch ftp:// URLs
|
||||||
|
- Windows binaries are no longer signed with a self-signed Authenticode certificate, it gave no trust and triggered antivirus false positives
|
||||||
|
|||||||
@ -1,13 +1,25 @@
|
|||||||
3proxy-1.0.0 Вышел 22 Августа 2026
|
3proxy-1.0.1 Вышел 10 Октября 2026
|
||||||
|
|
||||||
Изменений в коде 3proxy нет, этот выпуск меняет только сборку, подписывание и публикацию пакетов.
|
! Исправление: падение (segmentation fault) при перезагрузке конфигурации (SIGUSR1) на нагруженном сервере: закрывающаяся сессия могла обращаться к службе после того, как перезагрузка её освободила; гонка существовала с 0.9.7, а добавленная в 0.9.9 задержка закрытия (linger) в 5 секунд сделала её гораздо вероятнее (#1278)
|
||||||
|
! Исправление: -Di и -De (привязка к интерфейсу) не применялись к сокетам SOCKSv5 UDP ASSOCIATE и BIND, к соединению данных FTP прокси и к обратному соединению (connect back) (#1277)
|
||||||
! Исправление: поддержка TLS, PCRE2 и PAM молча не включалась при сборке в системах, где /bin/sh не dash, то есть во всех дистрибутивах на основе RPM и в macOS; проверки наличия библиотек формировали тестовую программу через echo с escape-последовательностями, которые раскрывает только dash, поэтому все проверки завершались неудачно и возможности отключались без каких-либо сообщений
|
! Исправление: SOCKSv5 UDP ASSOCIATE по IPv6: адрес отправителя датаграммы обрезался, и ответ отправлялся не на тот адрес (#1279)
|
||||||
! Исправление: пакеты rpm собирались в Ubuntu и требовали glibc 2.38, libssl.so.3 и libpcre2-8, которых нет ни в одном дистрибутиве на основе RPM, поэтому установить их было невозможно нигде; теперь они собираются в AlmaLinux 8, 9 и 10 и содержат метку el8, el9 или el10, что покрывает RHEL, AlmaLinux, Rocky и CentOS Stream соответствующей версии
|
! Исправление: SOCKSv5 UDP ASSOCIATE: правило доступа с именами хостов срабатывало для любой датаграммы, отправленной на адрес, а не на имя; теперь адрес используется как имя хоста, так же как для запросов TCP
|
||||||
! Исправление: пакет rpm зависел от собственного интерпретатора /bin/3proxy, взятого из первой строки устанавливаемого файла конфигурации, и не устанавливался в el9 и el10, поскольку rpm приводит эту зависимость к /usr/bin/3proxy
|
! Исправление: запрос, изменённый pcre_rewrite, только записывался в журнал, а при прямом соединении серверу отправлялся без изменений; теперь сервер получает изменённые путь и строку запроса
|
||||||
! Исправление: пакеты deb требовали glibc 2.38 и libssl3t64 и устанавливались только в Ubuntu 24.04 и новее; теперь они собираются в Ubuntu 22.04 и устанавливаются в Ubuntu 22.04 и новее, а также в Debian 12 и новее
|
! Исправление: буфера могло не хватить для заголовков, добавляемых HTTP прокси, после того как pcre_rewrite увеличил запрос
|
||||||
+ Подписанные репозитории apt и dnf публикуются на https://3proxy.org/repo/ в двух каналах: current, собираемый из ветки master, и lts, собираемый из ветки 0.9; подписываются и пакеты, и метаданные репозитория
|
! Исправление: переполнение буфера в куче в pcre_rewrite: ссылка $N на группу, не участвовавшую в совпадении, выводилась своими цифрами, которые не учитывались при выделении памяти под результат
|
||||||
+ Двоичные файлы релиза публикуются с контрольными суммами SHA256, подписью OpenPGP и подтверждением происхождения сборки GitHub (build provenance attestation); образы docker также подписываются и снабжаются подтверждением
|
! Исправление: pcre_extend ничего не делал, добавленные им правила никогда не проверялись; в документации был описан аргумент, который команда не принимает
|
||||||
+ Ключ подписи релизов — RSA-4096, опубликован в репозитории как 3proxy-release-key.asc; rpm версии 4.14 и более ранние вообще не могут импортировать ключ Ed25519, что лишило бы RHEL 8 и производные от него возможности проверки
|
! Исправление: сертификаты, создаваемые для TLS MitM (openssl), не содержали идентификаторов ключа субъекта и издателя и отвергались строгой проверкой, в том числе клиентами macOS, OpenSSL с x509_strict и Python 3.13
|
||||||
+ Пакеты воспроизводимы: повторная сборка релиза даёт побайтово идентичные файлы deb и rpm, все отметки времени берутся из даты сборки, записанной для релиза
|
! Исправление: обращение по нулевому указателю в ftppr при PASS без USER и в smtpp при имени пользователя без хоста
|
||||||
- Для 32-битной ARM (armhf) публикуется только пакет deb, в Enterprise Linux нет сборки для 32-битной ARM
|
! Исправление: с wolfSSL на glibc не запускалась ни одна служба: стека потока по умолчанию не хватало для thread-local памяти wolfSSL, pthread_create() завершался ошибкой, о которой не сообщалось
|
||||||
|
! Исправление: dnspr не работал в Windows; сборки для Windows снова отвечают по UDP с отдельного сокета
|
||||||
|
+ Встроенный HTTP сервер: служба httpsrv с правилами http для отдачи файлов (из кэша или через sendfile / TransmitFile), перенаправлений, перезаписи, фиксированных ответов и proxypass для передачи запроса прокси, так что один порт может обслуживать и сайт, и прокси; admin — это httpsrv со страницами администрирования
|
||||||
|
+ Имена хостов в правилах доступа могут быть регулярными выражениями с префиксом pcre: (или regex:)
|
||||||
|
+ Команды transparent / notransparent: прозрачное проксирование встроено в 3proxy (netfilter в Linux, pf в BSD, socket для divert-to и ipfw fwd), TransparentPlugin удалён, конфигурация, загружающая его, продолжает работать
|
||||||
|
+ parent: вес можно задавать дробью (.5) или в процентах (50%); вес 0 означает резервный parent, который используется только когда отказали все parent его группы с ненулевым весом; отказавший parent исключается из следующей попытки того же соединения
|
||||||
|
+ parent extport / intport: диапазон локальных портов для исходящих соединений и для сокетов на стороне клиента (UDP ASSOCIATE, данные FTP)
|
||||||
|
+ parent, заданный именем хоста, разрешается для каждого соединения, если используется nserver, а не один раз при загрузке конфигурации
|
||||||
|
+ $$ в конфигурации обозначает одиночный знак доллара, доллар в кавычках — обычный символ
|
||||||
|
+ Пакет для OpenWrt (скрипт запуска procd, конфигурация UCI) и сборки OpenWrt для mipsel_24kc, mips_24kc, arm_cortex-a7_neon-vfpv4 и aarch64_cortex-a53
|
||||||
|
- pop3p, imapp, smtpp и ftppr не входят в сборку по умолчанию: собирайте с MAILPROXY=true и FTP=true (CMake: 3PROXY_USE_MAILPROXY, 3PROXY_USE_FTP); без них почтовые прокси работают как tlspr с согласованием STARTTLS, а ftppr отказывает клиентам
|
||||||
|
- FTP через HTTP прокси (адреса ftp://) также не входит в сборку по умолчанию и должен быть включён явно: собирайте с FTP=true (CMake: 3PROXY_USE_FTP), без этого HTTP прокси не обрабатывает адреса ftp://
|
||||||
|
- Двоичные файлы для Windows больше не подписываются самоподписанным сертификатом Authenticode: доверия он не давал и вызывал ложные срабатывания антивирусов
|
||||||
|
|||||||
@ -35,7 +35,7 @@ RUN TAG=$(curl -s https://api.github.com/repos/wolfSSL/wolfssl/releases/latest \
|
|||||||
make -j$(nproc) && make install
|
make -j$(nproc) && make install
|
||||||
|
|
||||||
FROM docker.io/alpine:latest AS buildenv
|
FROM docker.io/alpine:latest AS buildenv
|
||||||
RUN apk add --no-cache gcc make musl-dev pcre2-dev
|
RUN apk add --no-cache gcc make musl-dev linux-headers pcre2-dev
|
||||||
COPY --from=wolfssl /usr/local /usr/local
|
COPY --from=wolfssl /usr/local /usr/local
|
||||||
COPY . 3proxy
|
COPY . 3proxy
|
||||||
RUN cd 3proxy && mkdir -p bin &&\
|
RUN cd 3proxy && mkdir -p bin &&\
|
||||||
|
|||||||
@ -41,7 +41,7 @@ RUN TAG=$(curl -s https://api.github.com/repos/wolfSSL/wolfssl/releases/latest \
|
|||||||
make -j$(nproc) && make install
|
make -j$(nproc) && make install
|
||||||
|
|
||||||
FROM docker.io/alpine:latest AS buildenv
|
FROM docker.io/alpine:latest AS buildenv
|
||||||
RUN apk add --no-cache gcc make musl-dev
|
RUN apk add --no-cache gcc make musl-dev linux-headers
|
||||||
COPY --from=wolfssl /usr/local /usr/local
|
COPY --from=wolfssl /usr/local /usr/local
|
||||||
COPY . 3proxy
|
COPY . 3proxy
|
||||||
RUN cd 3proxy && mkdir -p bin &&\
|
RUN cd 3proxy && mkdir -p bin &&\
|
||||||
|
|||||||
@ -135,7 +135,7 @@ install: all
|
|||||||
install -d $(DESTDIR)$(MANDIR)/man8
|
install -d $(DESTDIR)$(MANDIR)/man8
|
||||||
install -m 644 man/3proxy.8 $(DESTDIR)$(MANDIR)/man8/3proxy.8
|
install -m 644 man/3proxy.8 $(DESTDIR)$(MANDIR)/man8/3proxy.8
|
||||||
for f in proxy socks pop3p imapp 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; \
|
if [ -f man/$$f.8 ] && [ -f bin/$(PREFIX)$$f ]; then install -m 644 man/$$f.8 $(DESTDIR)$(MANDIR)/man8/$(PREFIX)$$f.8; fi; \
|
||||||
done
|
done
|
||||||
install -m 644 man/3proxy_crypt.8 $(DESTDIR)$(MANDIR)/man8/$(CRYPT_PREFIX)crypt.8
|
install -m 644 man/3proxy_crypt.8 $(DESTDIR)$(MANDIR)/man8/$(CRYPT_PREFIX)crypt.8
|
||||||
install -d $(DESTDIR)$(MANDIR)/man5
|
install -d $(DESTDIR)$(MANDIR)/man5
|
||||||
|
|||||||
@ -123,15 +123,18 @@ INSTALL_BIN = $(INSTALL) -m 755
|
|||||||
INSTALL_DATA = $(INSTALL) -m 644
|
INSTALL_DATA = $(INSTALL) -m 644
|
||||||
INSTALL_OBJS = bin/3proxy \
|
INSTALL_OBJS = bin/3proxy \
|
||||||
bin/$(CRYPT_PREFIX)crypt \
|
bin/$(CRYPT_PREFIX)crypt \
|
||||||
bin/$(PREFIX)ftppr \
|
|
||||||
bin/$(PREFIX)imapp \
|
|
||||||
bin/$(PREFIX)pop3p \
|
|
||||||
bin/$(PREFIX)proxy \
|
bin/$(PREFIX)proxy \
|
||||||
bin/$(PREFIX)smtpp \
|
|
||||||
bin/$(PREFIX)socks \
|
bin/$(PREFIX)socks \
|
||||||
bin/$(PREFIX)tcppm \
|
bin/$(PREFIX)tcppm \
|
||||||
bin/$(PREFIX)tlspr \
|
bin/$(PREFIX)tlspr \
|
||||||
bin/$(PREFIX)udppm
|
bin/$(PREFIX)udppm
|
||||||
|
# the mail proxies and ftppr are only there when they were built
|
||||||
|
ifeq ($(MAILPROXY),true)
|
||||||
|
INSTALL_OBJS += bin/$(PREFIX)imapp bin/$(PREFIX)pop3p bin/$(PREFIX)smtpp
|
||||||
|
endif
|
||||||
|
ifeq ($(FTP),true)
|
||||||
|
INSTALL_OBJS += bin/$(PREFIX)ftppr
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
INSTALL_CFG = scripts/3proxy.cfg.chroot
|
INSTALL_CFG = scripts/3proxy.cfg.chroot
|
||||||
@ -189,7 +192,7 @@ install-man:
|
|||||||
$(INSTALL_DATA) man/3proxy.cfg.5 $(MANDIR5)
|
$(INSTALL_DATA) man/3proxy.cfg.5 $(MANDIR5)
|
||||||
$(INSTALL_DATA) man/3proxy.8 $(MANDIR8)
|
$(INSTALL_DATA) man/3proxy.8 $(MANDIR8)
|
||||||
for f in proxy socks pop3p imapp 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; \
|
if [ -f man/$$f.8 ] && [ -f bin/$(PREFIX)$$f ]; then $(INSTALL_DATA) man/$$f.8 $(MANDIR8)/$(PREFIX)$$f.8; fi; \
|
||||||
done
|
done
|
||||||
$(INSTALL_DATA) man/3proxy_crypt.8 $(MANDIR8)/$(CRYPT_PREFIX)crypt.8
|
$(INSTALL_DATA) man/3proxy_crypt.8 $(MANDIR8)/$(CRYPT_PREFIX)crypt.8
|
||||||
|
|
||||||
|
|||||||
@ -130,7 +130,7 @@ install: all
|
|||||||
install -d $(DESTDIR)$(MANDIR)/man8
|
install -d $(DESTDIR)$(MANDIR)/man8
|
||||||
install -m 644 man/3proxy.8 $(DESTDIR)$(MANDIR)/man8/3proxy.8
|
install -m 644 man/3proxy.8 $(DESTDIR)$(MANDIR)/man8/3proxy.8
|
||||||
for f in proxy socks pop3p imapp 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; \
|
if [ -f man/$$f.8 ] && [ -f bin/$(PREFIX)$$f ]; then install -m 644 man/$$f.8 $(DESTDIR)$(MANDIR)/man8/$(PREFIX)$$f.8; fi; \
|
||||||
done
|
done
|
||||||
install -m 644 man/3proxy_crypt.8 $(DESTDIR)$(MANDIR)/man8/$(CRYPT_PREFIX)crypt.8
|
install -m 644 man/3proxy_crypt.8 $(DESTDIR)$(MANDIR)/man8/$(CRYPT_PREFIX)crypt.8
|
||||||
install -d $(DESTDIR)$(MANDIR)/man5
|
install -d $(DESTDIR)$(MANDIR)/man5
|
||||||
|
|||||||
6
debian/changelog
vendored
6
debian/changelog
vendored
@ -1,3 +1,9 @@
|
|||||||
|
3proxy (1.0.1-1) buster; urgency=medium
|
||||||
|
|
||||||
|
*3proxy 1.0.1 initial build
|
||||||
|
|
||||||
|
-- z3APA3A <3apa3a@3proxy.org> Sat, 10 Oct 2026 16:21:01 +0000
|
||||||
|
|
||||||
3proxy (1.0.0-1) buster; urgency=medium
|
3proxy (1.0.0-1) buster; urgency=medium
|
||||||
|
|
||||||
*3proxy 1.0.0 initial build
|
*3proxy 1.0.0 initial build
|
||||||
|
|||||||
2
debian/control
vendored
2
debian/control
vendored
@ -14,5 +14,5 @@ Depends: ${shlibs:Depends}, ${misc:Depends}
|
|||||||
Description: tiny free proxy server
|
Description: tiny free proxy server
|
||||||
3Proxy tiny free proxy server is really tiny freeware proxy servers set.
|
3Proxy tiny free proxy server is really tiny freeware proxy servers set.
|
||||||
It includes HTTP proxy with HTTPS and FTP support, SOCKSv4/SOCKSv4.5/SOCKSv5 proxy (socks/socks.exe), POP3 proxy, SMTP proxy, FTP proxy, caching DNS proxy, TCP and UDP portmappers.
|
It includes HTTP proxy with HTTPS and FTP support, SOCKSv4/SOCKSv4.5/SOCKSv5 proxy (socks/socks.exe), POP3 proxy, SMTP proxy, FTP proxy, caching DNS proxy, TCP and UDP portmappers.
|
||||||
You can use every proxy as a standalone program (socks, proxy, tcppm, udppm, pop3p) or use combined program (3proxy). Combined proxy additionally supports features like access control, bandwidth limiting, limiting daily/weekly/monthly traffic amount, proxy chaining, log rotation, syslog and ODBC logging, etc.
|
You can use every proxy as a standalone program (socks, proxy, tcppm, udppm, tlspr) or use combined program (3proxy). Combined proxy additionally supports features like access control, bandwidth limiting, limiting daily/weekly/monthly traffic amount, proxy chaining, log rotation, syslog and ODBC logging, etc.
|
||||||
It's created to be small, simple and yet very functional.
|
It's created to be small, simple and yet very functional.
|
||||||
23
doc/changelog/1/0/1
Normal file
23
doc/changelog/1/0/1
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
! Fix: crash (segmentation fault) on configuration reload (SIGUSR1) on a busy server: a closing session could still use its service after the reload had freed it; the race existed since 0.9.7, the 5 second linger added in 0.9.9 made it much more likely (#1278)
|
||||||
|
! Fix: -Di and -De (bind to interface) were not applied to SOCKSv5 UDP ASSOCIATE and BIND sockets, the FTP proxy data connection and connect back (#1277)
|
||||||
|
! Fix: SOCKSv5 UDP ASSOCIATE over IPv6: the source address of a datagram was truncated and the reply was sent to the wrong address (#1279)
|
||||||
|
! Fix: SOCKSv5 UDP ASSOCIATE: an access rule with host names matched any datagram sent to a literal address; the address is used as the host name now, as it is for TCP requests
|
||||||
|
! Fix: a request rewritten with pcre_rewrite was only logged and was sent unchanged to the server on a direct connection; the rewritten path and query are what the server receives now
|
||||||
|
! Fix: buffer could be insufficient for the headers the HTTP proxy adds after a pcre_rewrite had grown the request
|
||||||
|
! Fix: heap buffer overflow in pcre_rewrite: a $N reference to a group which did not match was written out as its digits, which the space allocated for the result did not count
|
||||||
|
! Fix: pcre_extend did nothing, the rules it appended were never consulted; the manual described an argument the command does not take
|
||||||
|
! Fix: certificates generated for TLS MitM (openssl) carried no subject and authority key identifiers and were refused by strict verifiers, including macOS clients, OpenSSL with x509_strict and Python 3.13
|
||||||
|
! Fix: null pointer dereference in ftppr on PASS without USER and in smtpp on a user name without a host
|
||||||
|
! Fix: no service started with wolfSSL on glibc: the default thread stack was too small for wolfSSL thread-local storage, pthread_create() failed and the failure was not reported
|
||||||
|
! Fix: dnspr did not work on Windows; Windows builds answer UDP from a socket of their own again
|
||||||
|
+ Built-in HTTP server: httpsrv service with http rules to serve files (cached or with sendfile / TransmitFile), redirects, rewrites, fixed replies and proxypass to forward requests as the proxy does, so one port can serve both a site and a proxy; admin is httpsrv with the administration pages
|
||||||
|
+ Host names in access rules may be regular expressions with a pcre: (or regex:) prefix
|
||||||
|
+ transparent / notransparent commands: transparent proxying is built in (netfilter on Linux, pf on BSD, socket for divert-to and ipfw fwd), TransparentPlugin is removed and a configuration loading it keeps working
|
||||||
|
+ parent: weight may be written as a fraction (.5) or a percentage (50%); weight 0 is a fallback parent used only when every weighted parent of its group has failed; a failed parent is left out of the next attempt of the same connection
|
||||||
|
+ parent extport / intport: range of local ports for outgoing connections and for sockets facing the client (UDP ASSOCIATE, FTP data)
|
||||||
|
+ A parent given by host name is resolved for each connection when nserver is used, instead of once on configuration load
|
||||||
|
+ $$ in the configuration stands for a single dollar sign, a dollar inside quotes is ordinary text
|
||||||
|
+ OpenWrt package (procd init script, UCI configuration) and OpenWrt builds for mipsel_24kc, mips_24kc, arm_cortex-a7_neon-vfpv4 and aarch64_cortex-a53
|
||||||
|
- pop3p, imapp, smtpp and ftppr are not in a default build: build with MAILPROXY=true and FTP=true (CMake: 3PROXY_USE_MAILPROXY, 3PROXY_USE_FTP); without them the mail proxies run as tlspr negotiating STARTTLS, and ftppr refuses clients
|
||||||
|
- FTP over HTTP proxy (ftp:// URLs) is not in a default build either and has to be enabled explicitly: build with FTP=true (CMake: 3PROXY_USE_FTP), without it the HTTP proxy does not fetch ftp:// URLs
|
||||||
|
- Windows binaries are no longer signed with a self-signed Authenticode certificate, it gave no trust and triggered antivirus false positives
|
||||||
@ -1,5 +1,5 @@
|
|||||||
Name: 3proxy
|
Name: 3proxy
|
||||||
Version: 1.0.0
|
Version: 1.0.1
|
||||||
Release: 1%{?dist}
|
Release: 1%{?dist}
|
||||||
Summary: 3proxy tiny proxy server
|
Summary: 3proxy tiny proxy server
|
||||||
License: GPL/LGPL/Apache/BSD
|
License: GPL/LGPL/Apache/BSD
|
||||||
@ -36,11 +36,7 @@ make clean
|
|||||||
%files
|
%files
|
||||||
/bin/3proxy
|
/bin/3proxy
|
||||||
/bin/3proxy_crypt
|
/bin/3proxy_crypt
|
||||||
/bin/3proxy_ftppr
|
|
||||||
/bin/3proxy_imapp
|
|
||||||
/bin/3proxy_pop3p
|
|
||||||
/bin/3proxy_proxy
|
/bin/3proxy_proxy
|
||||||
/bin/3proxy_smtpp
|
|
||||||
/bin/3proxy_socks
|
/bin/3proxy_socks
|
||||||
/bin/3proxy_tcppm
|
/bin/3proxy_tcppm
|
||||||
/bin/3proxy_tlspr
|
/bin/3proxy_tlspr
|
||||||
|
|||||||
63
src/common.c
63
src/common.c
@ -683,6 +683,49 @@ int connectwithpoll(struct clientparam *param, SOCKET sock, struct sockaddr *sa,
|
|||||||
|
|
||||||
static int bindrange(struct clientparam *param, SOCKET sock, PROXYSOCKADDRTYPE *sa, uint32_t range, int *tries);
|
static int bindrange(struct clientparam *param, SOCKET sock, PROXYSOCKADDRTYPE *sa, uint32_t range, int *tries);
|
||||||
|
|
||||||
|
/* -Di / -De: ties a socket to the interface asked for, for TCP and UDP alike.
|
||||||
|
Where the option is set per protocol, family is the one of the address the
|
||||||
|
socket will be bound to. */
|
||||||
|
int bindtodevice(struct sockfuncs *sf, void *state, SOCKET sock, const char *device, int family){
|
||||||
|
if(!device) return 0;
|
||||||
|
#if defined SO_BINDTODEVICE
|
||||||
|
if(sf->_setsockopt(state, sock, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device) + 1))
|
||||||
|
return 1;
|
||||||
|
#elif defined IP_BOUND_IF
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
idx = if_nametoindex(device);
|
||||||
|
if(!idx || (family == AF_INET && sf->_setsockopt(state, sock, IPPROTO_IP, IP_BOUND_IF, &idx, sizeof(idx))))
|
||||||
|
return 1;
|
||||||
|
#ifndef NOIPV6
|
||||||
|
#ifndef IPV6_BOUND_IF
|
||||||
|
#define IPV6_BOUND_IF 125
|
||||||
|
#endif
|
||||||
|
if(family == AF_INET6 && sf->_setsockopt(state, sock, IPPROTO_IPV6, IPV6_BOUND_IF, &idx, sizeof(idx))) return 1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the external side, a socket to be bound to sinsl */
|
||||||
|
int extbindtodevice(struct clientparam *param, SOCKET sock){
|
||||||
|
#if defined SO_BINDTODEVICE || defined IP_BOUND_IF
|
||||||
|
return bindtodevice(¶m->srv->so, param->sostate, sock, param->srv->obindtodevice, *SAFAMILY(¶m->sinsl));
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the internal side, a socket to be bound to sincl */
|
||||||
|
int intbindtodevice(struct clientparam *param, SOCKET sock){
|
||||||
|
#if defined SO_BINDTODEVICE || defined IP_BOUND_IF
|
||||||
|
return bindtodevice(¶m->srv->so, param->sostate, sock, param->srv->ibindtodevice, *SAFAMILY(¶m->sincl));
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int doconnect(struct clientparam * param){
|
int doconnect(struct clientparam * param){
|
||||||
SASIZETYPE size;
|
SASIZETYPE size;
|
||||||
|
|
||||||
@ -732,25 +775,7 @@ int doconnect(struct clientparam * param){
|
|||||||
setopts(param->remsock, param->srv->srvsockopts);
|
setopts(param->remsock, param->srv->srvsockopts);
|
||||||
|
|
||||||
param->srv->so._setsockopt(param->sostate, param->remsock, SOL_SOCKET, SO_LINGER, (char *)&lg, sizeof(lg));
|
param->srv->so._setsockopt(param->sostate, param->remsock, SOL_SOCKET, SO_LINGER, (char *)&lg, sizeof(lg));
|
||||||
#if defined SO_BINDTODEVICE
|
if(extbindtodevice(param, param->remsock)) return 12;
|
||||||
if(param->srv->obindtodevice) {
|
|
||||||
if(param->srv->so._setsockopt(param->sostate, param->remsock, SOL_SOCKET, SO_BINDTODEVICE, param->srv->obindtodevice, strlen(param->srv->obindtodevice) + 1))
|
|
||||||
return 12;
|
|
||||||
}
|
|
||||||
#elif defined IP_BOUND_IF
|
|
||||||
if(param->srv->obindtodevice) {
|
|
||||||
int idx;
|
|
||||||
idx = if_nametoindex(param->srv->obindtodevice);
|
|
||||||
if(!idx || (*SAFAMILY(¶m->sinsl) == AF_INET && param->srv->so._setsockopt(param->sostate, param->remsock, IPPROTO_IP, IP_BOUND_IF, &idx, sizeof(idx))))
|
|
||||||
return 12;
|
|
||||||
#ifndef NOIPV6
|
|
||||||
#ifndef IPV6_BOUND_IF
|
|
||||||
#define IPV6_BOUND_IF 125
|
|
||||||
#endif
|
|
||||||
if(*SAFAMILY(¶m->sinsl) == AF_INET6 && param->srv->so._setsockopt(param->sostate, param->remsock, IPPROTO_IPV6, IPV6_BOUND_IF, &idx, sizeof(idx))) return 12;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef WITH_UN
|
#ifdef WITH_UN
|
||||||
if(*SAFAMILY(¶m->sinsl) != AF_UNIX)
|
if(*SAFAMILY(¶m->sinsl) != AF_UNIX)
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -129,6 +129,7 @@ void * ftpprchild(struct clientparam* param) {
|
|||||||
clidatasock = INVALID_SOCKET;
|
clidatasock = INVALID_SOCKET;
|
||||||
}
|
}
|
||||||
if ((clidatasock=socket(SASOCK(¶m->sincl), SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {RETURN(821);}
|
if ((clidatasock=socket(SASOCK(¶m->sincl), SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {RETURN(821);}
|
||||||
|
if(intbindtodevice(param, clidatasock)){RETURN(822);}
|
||||||
*SAPORT(¶m->sincl) = 0;
|
*SAPORT(¶m->sincl) = 0;
|
||||||
if(bindwithrange(param, clidatasock, ¶m->sincl, param->intport)){RETURN(822);}
|
if(bindwithrange(param, clidatasock, ¶m->sincl, param->intport)){RETURN(822);}
|
||||||
if (pasv) {
|
if (pasv) {
|
||||||
|
|||||||
@ -391,6 +391,9 @@ int readconfig(FILE * fp);
|
|||||||
void initcommands(void);
|
void initcommands(void);
|
||||||
int connectwithpoll(struct clientparam *param, SOCKET sock, struct sockaddr *sa, SASIZETYPE size, int to);
|
int connectwithpoll(struct clientparam *param, SOCKET sock, struct sockaddr *sa, SASIZETYPE size, int to);
|
||||||
int bindwithrange(struct clientparam *param, SOCKET sock, PROXYSOCKADDRTYPE *sa, uint32_t range);
|
int bindwithrange(struct clientparam *param, SOCKET sock, PROXYSOCKADDRTYPE *sa, uint32_t range);
|
||||||
|
int bindtodevice(struct sockfuncs *sf, void *state, SOCKET sock, const char *device, int family);
|
||||||
|
int extbindtodevice(struct clientparam *param, SOCKET sock);
|
||||||
|
int intbindtodevice(struct clientparam *param, SOCKET sock);
|
||||||
#ifdef WITH_PCRE
|
#ifdef WITH_PCRE
|
||||||
/* One regular expression implementation for the whole program: the pcre
|
/* One regular expression implementation for the whole program: the pcre
|
||||||
commands and every pattern that carries a pcre: prefix. */
|
commands and every pattern that carries a pcre: prefix. */
|
||||||
|
|||||||
@ -856,29 +856,11 @@ int MODULEMAINFUNC (int argc, char** argv){
|
|||||||
srv.so._setsockopt(srv.so.state, sock, SOL_SOCKET, SO_REUSEPORT, (char *)&opt, sizeof(int));
|
srv.so._setsockopt(srv.so.state, sock, SOL_SOCKET, SO_REUSEPORT, (char *)&opt, sizeof(int));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#if defined SO_BINDTODEVICE
|
#if defined SO_BINDTODEVICE || defined IP_BOUND_IF
|
||||||
if(srv.ibindtodevice && srv.so._setsockopt(srv.so.state, sock, SOL_SOCKET, SO_BINDTODEVICE, srv.ibindtodevice, strlen(srv.ibindtodevice) + 1)) {
|
if(bindtodevice(&srv.so, srv.so.state, sock, srv.ibindtodevice, *SAFAMILY(&srv.intsa))) {
|
||||||
dolog(&defparam, (unsigned char *)"failed to bind device");
|
dolog(&defparam, (unsigned char *)"failed to bind device");
|
||||||
return -12;
|
return -12;
|
||||||
}
|
}
|
||||||
#elif defined IP_BOUND_IF
|
|
||||||
if(srv.ibindtodevice){
|
|
||||||
int idx;
|
|
||||||
idx = if_nametoindex(srv.ibindtodevice);
|
|
||||||
if(!idx || (*SAFAMILY(&srv.intsa) == AF_INET && setsockopt(sock, IPPROTO_IP, IP_BOUND_IF, &idx, sizeof(idx)))) {
|
|
||||||
dolog(&defparam, (unsigned char *)"failed to bind device");
|
|
||||||
return -12;
|
|
||||||
}
|
|
||||||
#ifndef NOIPV6
|
|
||||||
#ifndef IPV6_BOUND_IF
|
|
||||||
#define IPV6_BOUND_IF 125
|
|
||||||
#endif
|
|
||||||
if((*SAFAMILY(&srv.intsa) == AF_INET6 && srv.so._setsockopt(srv.so.state, sock, IPPROTO_IPV6, IPV6_BOUND_IF, &idx, sizeof(idx)))) {
|
|
||||||
dolog(&defparam, (unsigned char *)"failed to bind device");
|
|
||||||
return -12;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#ifdef WITH_UN
|
#ifdef WITH_UN
|
||||||
@ -1032,6 +1014,15 @@ int MODULEMAINFUNC (int argc, char** argv){
|
|||||||
setopts(new_sock, srv.cbcsockopts);
|
setopts(new_sock, srv.cbcsockopts);
|
||||||
|
|
||||||
parsehost(srv.family, cbc_string, (struct sockaddr *)&defparam.sincr);
|
parsehost(srv.family, cbc_string, (struct sockaddr *)&defparam.sincr);
|
||||||
|
#if defined SO_BINDTODEVICE || defined IP_BOUND_IF
|
||||||
|
/* as for a listening socket, an interface that cannot be
|
||||||
|
bound to is not worth retrying */
|
||||||
|
if(bindtodevice(&so, so.state, new_sock, srv.ibindtodevice, *SAFAMILY(&defparam.sincr))) {
|
||||||
|
dolog(&defparam, (unsigned char *)"failed to bind device");
|
||||||
|
so._closesocket(so.state, new_sock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if(connectwithpoll(NULL, new_sock,(struct sockaddr *)&defparam.sincr,SASIZE(&defparam.sincr),CONNBACK_TO)) {
|
if(connectwithpoll(NULL, new_sock,(struct sockaddr *)&defparam.sincr,SASIZE(&defparam.sincr),CONNBACK_TO)) {
|
||||||
so._closesocket(so.state, new_sock);
|
so._closesocket(so.state, new_sock);
|
||||||
new_sock = INVALID_SOCKET;
|
new_sock = INVALID_SOCKET;
|
||||||
@ -1342,7 +1333,16 @@ void srvfree(struct srvparam * srv){
|
|||||||
if(srv->cbsock != INVALID_SOCKET) so._closesocket(srv->so.state, srv->cbsock);
|
if(srv->cbsock != INVALID_SOCKET) so._closesocket(srv->so.state, srv->cbsock);
|
||||||
srv->cbsock = INVALID_SOCKET;
|
srv->cbsock = INVALID_SOCKET;
|
||||||
srv->service = S_ZOMBIE;
|
srv->service = S_ZOMBIE;
|
||||||
while(srv->child) usleep(SLEEPTIME * 100);
|
/* under the mutex, so the last child has let go of it before it is destroyed */
|
||||||
|
for(;;){
|
||||||
|
struct clientparam *child;
|
||||||
|
|
||||||
|
_3proxy_mutex_lock(&srv->counter_mutex);
|
||||||
|
child = srv->child;
|
||||||
|
_3proxy_mutex_unlock(&srv->counter_mutex);
|
||||||
|
if(!child) break;
|
||||||
|
usleep(SLEEPTIME * 100);
|
||||||
|
}
|
||||||
#ifndef STDMAIN
|
#ifndef STDMAIN
|
||||||
if(srv->filter){
|
if(srv->filter){
|
||||||
while(srv->nfilters){
|
while(srv->nfilters){
|
||||||
@ -1387,23 +1387,14 @@ void srvfree(struct srvparam * srv){
|
|||||||
void freeparam(struct clientparam * param) {
|
void freeparam(struct clientparam * param) {
|
||||||
if(param->srv){
|
if(param->srv){
|
||||||
if(param->srv->so.freefunc) param->srv->so.freefunc(param->sostate);
|
if(param->srv->so.freefunc) param->srv->so.freefunc(param->sostate);
|
||||||
_3proxy_mutex_lock(¶m->srv->counter_mutex);
|
|
||||||
#ifndef STDMAIN
|
#ifndef STDMAIN
|
||||||
if(param->srv->service == S_UDPPM) hashdelete(&udp_table, param);
|
if(param->srv->service == S_UDPPM){
|
||||||
#endif
|
_3proxy_mutex_lock(¶m->srv->counter_mutex);
|
||||||
if(param->prev || param->next || param->srv->child == param){
|
hashdelete(&udp_table, param);
|
||||||
if(param->prev){
|
|
||||||
param->prev->next = param->next;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
param->srv->child = param->next;
|
|
||||||
if(param->next){
|
|
||||||
param->next->prev = param->prev;
|
|
||||||
}
|
|
||||||
(param->srv->childcount)--;
|
|
||||||
}
|
|
||||||
_3proxy_mutex_unlock(¶m->srv->counter_mutex);
|
_3proxy_mutex_unlock(¶m->srv->counter_mutex);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
if(param->clibuf) free(param->clibuf);
|
if(param->clibuf) free(param->clibuf);
|
||||||
if(param->srvbuf) free(param->srvbuf);
|
if(param->srvbuf) free(param->srvbuf);
|
||||||
if(param->srv) {
|
if(param->srv) {
|
||||||
@ -1442,6 +1433,24 @@ void freeparam(struct clientparam * param) {
|
|||||||
}
|
}
|
||||||
if(param->connlim) stopconnlims(param);
|
if(param->connlim) stopconnlims(param);
|
||||||
#endif
|
#endif
|
||||||
|
/* Leaving the service comes last. Once its last child is gone, srvfree()
|
||||||
|
frees the service along with its socket functions, filters and mutex,
|
||||||
|
and a close above may have lingered for seconds before getting here. */
|
||||||
|
if(param->srv){
|
||||||
|
_3proxy_mutex_lock(¶m->srv->counter_mutex);
|
||||||
|
if(param->prev || param->next || param->srv->child == param){
|
||||||
|
if(param->prev){
|
||||||
|
param->prev->next = param->next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
param->srv->child = param->next;
|
||||||
|
if(param->next){
|
||||||
|
param->next->prev = param->prev;
|
||||||
|
}
|
||||||
|
(param->srv->childcount)--;
|
||||||
|
}
|
||||||
|
_3proxy_mutex_unlock(¶m->srv->counter_mutex);
|
||||||
|
}
|
||||||
if(param->hostname) free(param->hostname);
|
if(param->hostname) free(param->hostname);
|
||||||
if(param->username) free(param->username);
|
if(param->username) free(param->username);
|
||||||
if(param->password) free(param->password);
|
if(param->password) free(param->password);
|
||||||
|
|||||||
@ -63,7 +63,7 @@ int sockrecvfrom(struct clientparam *param, SOCKET sock, struct sockaddr * sin,
|
|||||||
if(conf.timetoexit) return EOF;
|
if(conf.timetoexit) return EOF;
|
||||||
res = param?param->srv->so._poll(param->sostate, &fds, 1, to):so._poll(so.state, &fds, 1, to);
|
res = param?param->srv->so._poll(param->sostate, &fds, 1, to):so._poll(so.state, &fds, 1, to);
|
||||||
if (res<1) return 0;
|
if (res<1) return 0;
|
||||||
sasize = SASIZE(sin);
|
sasize = sizeof(PROXYSOCKADDRTYPE);
|
||||||
do {
|
do {
|
||||||
res = param?param->srv->so._recvfrom(param->sostate, sock, (char *)buf, bufsize, 0, (struct sockaddr *)sin, &sasize):so._recvfrom(so.state, sock, (char *)buf, bufsize, 0, (struct sockaddr *)sin, &sasize);
|
res = param?param->srv->so._recvfrom(param->sostate, sock, (char *)buf, bufsize, 0, (struct sockaddr *)sin, &sasize):so._recvfrom(so.state, sock, (char *)buf, bufsize, 0, (struct sockaddr *)sin, &sasize);
|
||||||
} while (res < 0 && (errno == EAGAIN || errno == EINTR));
|
} while (res < 0 && (errno == EAGAIN || errno == EINTR));
|
||||||
|
|||||||
@ -185,6 +185,7 @@ void * sockschild(struct clientparam* param) {
|
|||||||
if(command == 2){
|
if(command == 2){
|
||||||
if ((param->remsock=param->srv->so._socket(param->sostate, SASOCK(¶m->req), SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {RETURN (11);}
|
if ((param->remsock=param->srv->so._socket(param->sostate, SASOCK(¶m->req), SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {RETURN (11);}
|
||||||
setopts(param->remsock, param->srv->lissockopts);
|
setopts(param->remsock, param->srv->lissockopts);
|
||||||
|
if(extbindtodevice(param, param->remsock)) {RETURN (12);}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -244,6 +245,7 @@ fflush(stderr);
|
|||||||
#else
|
#else
|
||||||
fcntl(param->clisock, F_SETFL, O_NONBLOCK | fcntl(param->clisock, F_GETFL));
|
fcntl(param->clisock, F_SETFL, O_NONBLOCK | fcntl(param->clisock, F_GETFL));
|
||||||
#endif
|
#endif
|
||||||
|
if(intbindtodevice(param, param->clisock)) {RETURN (12);}
|
||||||
sin = param->sincl;
|
sin = param->sincl;
|
||||||
*SAPORT(&sin) = 0;
|
*SAPORT(&sin) = 0;
|
||||||
/* the port the client is told to send its datagrams to */
|
/* the port the client is told to send its datagrams to */
|
||||||
|
|||||||
@ -121,6 +121,11 @@ int udpbind(struct clientparam *param)
|
|||||||
fcntl(s, F_SETFL, O_NONBLOCK | fcntl(s, F_GETFL));
|
fcntl(s, F_SETFL, O_NONBLOCK | fcntl(s, F_GETFL));
|
||||||
#endif
|
#endif
|
||||||
param->remsock = s;
|
param->remsock = s;
|
||||||
|
if (extbindtodevice(param, param->remsock)) {
|
||||||
|
param->srv->so._closesocket(param->sostate, param->remsock);
|
||||||
|
param->remsock = INVALID_SOCKET;
|
||||||
|
return 12;
|
||||||
|
}
|
||||||
if (bindwithrange(param, param->remsock, ¶m->sinsl, param->extport)) {
|
if (bindwithrange(param, param->remsock, ¶m->sinsl, param->extport)) {
|
||||||
if (param->extport) {
|
if (param->extport) {
|
||||||
param->srv->so._closesocket(param->sostate, param->remsock);
|
param->srv->so._closesocket(param->sostate, param->remsock);
|
||||||
|
|||||||
@ -1,14 +1,14 @@
|
|||||||
#ifndef VERSION
|
#ifndef VERSION
|
||||||
#define VERSION "3proxy-1.0.0"
|
#define VERSION "3proxy-1.0.1"
|
||||||
#endif
|
#endif
|
||||||
#ifndef BUILDDATE
|
#ifndef BUILDDATE
|
||||||
#define BUILDDATE "260822121300"
|
#define BUILDDATE "261010162101"
|
||||||
#endif
|
#endif
|
||||||
#define MAJOR3PROXY 1
|
#define MAJOR3PROXY 1
|
||||||
#define SUBMAJOR3PROXY 0
|
#define SUBMAJOR3PROXY 0
|
||||||
#define MINOR3PROXY 0
|
#define MINOR3PROXY 1
|
||||||
#define SUBMINOR3PROXY 0
|
#define SUBMINOR3PROXY 0
|
||||||
#define RELEASE3PROXY "3proxy-1.0.0(" BUILDDATE ")\0"
|
#define RELEASE3PROXY "3proxy-1.0.1(" BUILDDATE ")\0"
|
||||||
#ifndef YEAR3PROXY
|
#ifndef YEAR3PROXY
|
||||||
#define YEAR3PROXY "2026"
|
#define YEAR3PROXY "2026"
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user