Compare commits

...

86 Commits

Author SHA1 Message Date
Vladimir Dubrovin
41c120c527 Update build-win64.yml 2026-05-27 21:04:23 +03:00
Vladimir Dubrovin
cadf0e7909 Update build-win64.yml 2026-05-27 20:49:17 +03:00
Vladimir Dubrovin
867a26bfa3 Update build-win64.yml 2026-05-27 20:36:02 +03:00
Vladimir Dubrovin
2cb6297968 Documentation update 2026-05-27 17:06:48 +03:00
Vladimir Dubrovin
d66311a045 Support STATIC and LIBSTATIC in Makefile's, fix dockerfiles 2026-05-27 17:04:34 +03:00
Vladimir Dubrovin
905e3d3152 support IPv6 with NOSTDRESOLVE 2026-05-27 17:03:17 +03:00
Vladimir Dubrovin
7c08432a70 do not use FD_SETSIZE on Windows
Some checks failed
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Has been cancelled
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Has been cancelled
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Has been cancelled
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Has been cancelled
2026-05-22 20:16:56 +03:00
Vladimir Dubrovin
d4554cfabd Do not build PCRE/SSL with Watcom 2026-05-22 19:17:29 +03:00
Vladimir Dubrovin
1aecfa7995 Use C89 style declarations 2026-05-22 19:03:14 +03:00
Vladimir Dubrovin
289d2f5211 Use C89 style declarations 2026-05-22 18:57:23 +03:00
Vladimir Dubrovin
94efc7f7a6 Allow run workflows manually 2026-05-22 18:20:13 +03:00
Vladimir Dubrovin
d34c036eb7 Make build workflows manual 2026-05-22 18:13:02 +03:00
Vladimir Dubrovin
4bf1f3990b Use -lbcrypt in Makefile.win 2026-05-22 18:06:56 +03:00
Vladimir Dubrovin
a639bcb017 Fix: unneeded poll in sockmap 2026-05-22 17:57:15 +03:00
Vladimir Dubrovin
bed3977575 Merge branch 'master' of https://github.com/3proxy/3proxy 2026-05-22 17:55:57 +03:00
Vladimir Dubrovin
16af910f3a Fix: non-initialized mutex (crash under Windows) 2026-05-22 16:57:53 +03:00
Vladimir Dubrovin
7c1bc48c85 Fix socks v5 parent with no auth
Some checks failed
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Has been cancelled
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Has been cancelled
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Has been cancelled
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Has been cancelled
2026-05-15 18:45:47 +03:00
Vladimir Dubrovin
05c4832c6c Minor cleanups 2026-05-13 23:21:13 +03:00
Vladimir Dubrovin
381ef993a7 Minor logging improvement / code cleanup
Some checks failed
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Has been cancelled
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Has been cancelled
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Has been cancelled
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Has been cancelled
2026-05-12 21:21:59 +03:00
Vladimir Dubrovin
1de06c5059 Fix invalid buffer calculation in sockmap 2026-05-12 21:06:31 +03:00
Vladimir Dubrovin
aaa04116a8 Fix issues with -s
Some checks failed
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Has been cancelled
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Has been cancelled
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Has been cancelled
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Has been cancelled
2026-05-08 20:43:02 +03:00
Vladimir Dubrovin
5fdd4a4d6f NOODBC inverted to WITH_ODBC 2026-05-08 20:30:14 +03:00
Vladimir Dubrovin
7871279fae Support namespaces for UDP in socks 2026-05-08 20:21:04 +03:00
Vladimir Dubrovin
ff15a8d480 Update copyright 2026-05-08 19:25:33 +03:00
Vladimir Dubrovin
95029e9e41 Use blake2 hashsize 2026-05-08 19:14:28 +03:00
Vladimir Dubrovin
6286bfcd6e Fix crypt passwords 2026-05-08 19:00:14 +03:00
Vladimir Dubrovin
b1d21cbdca Copyright update 2026-05-08 18:07:08 +03:00
Vladimir Dubrovin
978f351560 Add compatiblity with older SSL versions 2026-05-08 17:16:47 +03:00
Vladimir Dubrovin
41d1fa8b00 Do not use OSSL_LIB_CTX 2026-05-08 17:03:00 +03:00
Vladimir Dubrovin
8c638fcaff Revert usage of OpenSSL blake2 implementation 2026-05-08 16:45:44 +03:00
Vladimir Dubrovin
6963af7614 Do not use OSSL_PARAM_DIGEST_SIZE for blake2 in openssl 2026-05-08 16:14:09 +03:00
Vladimir Dubrovin
f8c22d5f91 Fix: symbols collision with openssl, could lead to crash
Some checks are pending
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Waiting to run
2026-05-08 14:03:47 +03:00
Vladimir Dubrovin
c104203765 Fix memory leak in hash functions 2026-05-08 12:10:08 +03:00
Vladimir Dubrovin
45c3b89484 3proxy_crypt cleanup
Some checks are pending
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Waiting to run
2026-05-07 23:21:09 +03:00
Vladimir Dubrovin
0d7f05b05b set hostname in proxy if hostname is numeric
Some checks are pending
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Waiting to run
2026-05-07 19:10:36 +03:00
Vladimir Dubrovin
750bb38907 Do not fail on -n 2026-05-07 19:10:13 +03:00
Vladimir Dubrovin
46cff56cf4 Use EVP_MD_CTX_reset instead of free/new 2026-05-07 18:47:06 +03:00
Vladimir Dubrovin
d0d3b90226 Fix $1$ crypt 2026-05-07 18:34:38 +03:00
Vladimir Dubrovin
7a139e59a5 Use UDPMAP request address to limit client, not server 2026-05-07 16:07:59 +03:00
Vladimir Dubrovin
ff7f4b8ea6 Dynamic link with ssl/pcre by default, static as option in makefiles
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
2026-05-07 11:55:42 +03:00
Vladimir Dubrovin
ec48b7f30e Clear mingw warnings
Some checks are pending
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Waiting to run
2026-05-06 23:07:16 +03:00
Vladimir Dubrovin
88a09bc3ff Fix socks v5 derivations from standard 2026-05-06 23:02:04 +03:00
Vladimir Dubrovin
0e13f57139 Allocate udp buffer dynamically 2026-05-06 22:45:00 +03:00
Vladimir Dubrovin
cbab76fe41 do not use static linking for .so
Some checks failed
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Has been cancelled
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Has been cancelled
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Has been cancelled
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Has been cancelled
2026-05-05 18:38:45 +03:00
Vladimir Dubrovin
fb9337c030 Add option for static libraries linking (ssl / pcre2 / pam) 2026-05-05 18:34:58 +03:00
Vladimir Dubrovin
ef9386e29d More accurate flags in linking 2026-05-05 18:13:32 +03:00
Vladimir Dubrovin
334de0658c update datatypes 2026-05-05 15:27:55 +03:00
Vladimir Dubrovin
ec469fa2a6 Fix: buffer size in hash
Some checks are pending
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Waiting to run
2026-05-04 21:55:20 +03:00
Vladimir Dubrovin
fbd1788f4c increase stack size 2026-05-04 21:34:13 +03:00
Vladimir Dubrovin
830b2d39d1 Use standard malloc functions
Some checks are pending
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Waiting to run
2026-05-04 18:50:02 +03:00
Vladimir Dubrovin
a338a0c689 Speedup passwords lists 2026-05-04 18:37:18 +03:00
Vladimir Dubrovin
af8a6e0b91 minimize blake2 usage for hashing 2026-05-04 16:48:07 +03:00
Vladimir Dubrovin
2997533287 Use only defined PCRE2 options
Some checks are pending
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Waiting to run
2026-05-04 12:46:33 +03:00
Vladimir Dubrovin
5f06879843 Fix: crash on standalone services 2026-05-04 12:03:02 +03:00
Vladimir Dubrovin
da8a8615f4 Remove UDPASSOC check from tcp sockmap
Some checks failed
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Has been cancelled
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Has been cancelled
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Has been cancelled
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Has been cancelled
2026-05-02 15:36:21 +03:00
Vladimir Dubrovin
51a82613a6 Allow to set internal / external namespace on linux 2026-05-02 14:49:35 +03:00
Vladimir Dubrovin
b87e998e4d remove 'usentlm' option 2026-05-02 13:58:56 +03:00
Vladimir Dubrovin
4068a6955f Fix UDP parent for SOCKSv5
Some checks are pending
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Waiting to run
2026-05-02 00:00:45 +03:00
Vladimir Dubrovin
07c1dc1462 Fix shutdown for Windows
Some checks are pending
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Waiting to run
2026-05-01 19:26:39 +03:00
Vladimir Dubrovin
acce67a512 Fix NULL address request for UDP ASSOC 2026-05-01 17:26:06 +03:00
Vladimir Dubrovin
e986f8a747 FIx hanging connections in sockmap 2026-05-01 17:19:23 +03:00
Vladimir Dubrovin
314503d8df SOCKSv5 parent udp support (initial, untested) 2026-05-01 15:13:53 +03:00
Vladimir Dubrovin
8107f03062 Move PCRE/SSL to main code 2026-05-01 15:11:08 +03:00
Vladimir Dubrovin
a3fb7aff07 Clean up UDP code 2026-04-30 11:32:12 +03:00
Vladimir Dubrovin
b1ac46da79 Remove linux futext implementation
Some checks failed
Build Win32 3proxy-lite with Watcom / ${{ matrix.target }} (windows-2022) (push) Has been cancelled
Build Win32 3proxy with MSVC / ${{ matrix.target }} (windows-2022) (push) Has been cancelled
Build Win64 3proxy with MSVC / ${{ matrix.target }} (windows-2022) (push) Has been cancelled
Build Win-arm64 3proxy with MSVC / ${{ matrix.target }} (windows-2022) (push) Has been cancelled
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Has been cancelled
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Has been cancelled
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Has been cancelled
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Has been cancelled
2026-04-28 18:06:54 +03:00
Vladimir Dubrovin
d125261e8c fix: hashtables on recsize < 4 2026-04-28 16:32:30 +03:00
Vladimir Dubrovin
a4527783d6 Correctly process half-closed connections; add grace sleep before closing sockets 2026-04-28 16:15:18 +03:00
Vladimir Dubrovin
fb70d06d3e Add linger sleep on connection close 2026-04-28 14:55:37 +03:00
Vladimir Dubrovin
57d687fcb8 add 3proxy_crypt man 2026-04-28 14:41:14 +03:00
Vladimir Dubrovin
ada24a98ec Use semaphore/mutex insted of pipe for threads sync 2026-04-28 14:00:15 +03:00
Vladimir Dubrovin
ba2584cebf change 3proxy.cfg.3 to 3proxy.cfg.5 2026-04-28 12:34:53 +03:00
Vladimir Dubrovin
05096c222a Return standalone udppm; do not build standalone modules by default in cmake
Allow to set prefix in cmake, 3proxy_ by default
2026-04-28 12:21:11 +03:00
Vladimir Dubrovin
6c3c5f31a2 Update mans
Some checks are pending
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Waiting to run
2026-04-27 21:11:25 +03:00
Vladimir Dubrovin
319a74de06 Update proxymain.c 2026-04-27 20:12:28 +03:00
Vladimir Dubrovin
e088a5d7f9 Remove udppm from build 2026-04-27 20:05:34 +03:00
Vladimir Dubrovin
f01c8bfee9 Code cleanup 2026-04-27 19:58:34 +03:00
Vladimir Dubrovin
a7cdfa578d split auth.c 2026-04-27 15:30:35 +03:00
Vladimir Dubrovin
d52701518d udppm switched to hashtable and supports multiple connections; no standalone udppm 2026-04-27 15:12:39 +03:00
Vladimir Dubrovin
7ddea44ffd Fix: blake crypt
Some checks are pending
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Waiting to run
2026-04-27 13:23:32 +03:00
Vladimir Dubrovin
760a521df8 remove pwl_mutex
Some checks are pending
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Waiting to run
2026-04-26 20:43:13 +03:00
Vladimir Dubrovin
62ceb36157 Use hashtables for password lists 2026-04-26 20:38:58 +03:00
Vladimir Dubrovin
62be3c7b5b cash the hash for auth cache 2026-04-26 19:56:38 +03:00
Vladimir Dubrovin
85c431b96e Merge branch 'master' of https://github.com/3proxy/3proxy 2026-04-25 11:52:57 +03:00
Vladimir Dubrovin
90c312f4cd Changelog added 2026-04-25 11:52:54 +03:00
Vladimir Dubrovin
451b3d180c Allow hashtables to grow index
Some checks failed
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Has been cancelled
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Has been cancelled
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Has been cancelled
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Has been cancelled
2026-04-24 21:08:57 +03:00
Vladimir Dubrovin
f63a83f554 Fix blake2 for watcom 2026-04-24 18:13:30 +03:00
145 changed files with 6225 additions and 4783 deletions

View File

@ -1,9 +1,7 @@
name: RPM/DEB build aarch64 name: RPM/DEB build aarch64
on: on:
push: workflow_dispatch:
branches: [ "master", "test-ci" ]
paths: [ 'RELEASE', '.github/workflows/build-rpm-arm64.yml' ]
jobs: jobs:
ci: ci:

View File

@ -1,9 +1,7 @@
name: RPM/DEB build armhf name: RPM/DEB build armhf
on: on:
push: workflow_dispatch:
branches: [ "master", "test-ci" ]
paths: [ 'RELEASE', '.github/workflows/build-rpm-armhf.yml' ]
jobs: jobs:
ci: ci:

View File

@ -1,9 +1,7 @@
name: RPM/DEB build x86-64 name: RPM/DEB build x86-64
on: on:
push: workflow_dispatch:
branches: [ "master", "test-ci" ]
paths: [ 'RELEASE', '.github/workflows/build-rpm-x86-64.yml' ]
jobs: jobs:
ci: ci:

View File

@ -1,9 +1,7 @@
name: Build Win32 3proxy-lite with Watcom name: Build Win32 3proxy-lite with Watcom
on: on:
push: workflow_dispatch:
branches: [ "master" ]
paths: [ 'RELEASE', '.github/workflows/build-watcom.yml' ]
jobs: jobs:
ci: ci:
@ -45,7 +43,7 @@ jobs:
mkdir dist\3proxy\doc\ru mkdir dist\3proxy\doc\ru
mkdir dist\3proxy\doc\html mkdir dist\3proxy\doc\html
mkdir dist\3proxy\doc\html\plugins mkdir dist\3proxy\doc\html\plugins
mkdir dist\3proxy\doc\html\man3 mkdir dist\3proxy\doc\html\man5
mkdir dist\3proxy\doc\html\man8 mkdir dist\3proxy\doc\html\man8
mkdir dist\3proxy\doc\devel mkdir dist\3proxy\doc\devel
copy bin\3proxy.exe dist\3proxy\bin\ copy bin\3proxy.exe dist\3proxy\bin\
@ -57,7 +55,7 @@ jobs:
copy doc\html\*.* dist\3proxy\doc\html\ copy doc\html\*.* dist\3proxy\doc\html\
copy doc\html\plugins\*.* dist\3proxy\doc\html\plugins\ copy doc\html\plugins\*.* dist\3proxy\doc\html\plugins\
copy doc\html\man8\*.* dist\3proxy\doc\html\man8\ copy doc\html\man8\*.* dist\3proxy\doc\html\man8\
copy doc\html\man3\*.* dist\3proxy\doc\html\man3\ copy doc\html\man5\*.* dist\3proxy\doc\html\man5\
copy doc\devel\*.rtf dist\3proxy\doc\devel\ copy doc\devel\*.rtf dist\3proxy\doc\devel\
copy copying dist\3proxy\ copy copying dist\3proxy\
copy authors dist\3proxy\ copy authors dist\3proxy\

View File

@ -1,9 +1,7 @@
name: Build Win32 3proxy with MSVC name: Build Win32 3proxy with MSVC
on: on:
push: workflow_dispatch:
branches: [ "master" ]
paths: [ 'RELEASE', '.github/workflows/build-win32.yml' ]
jobs: jobs:
ci: ci:
@ -51,7 +49,7 @@ jobs:
mkdir dist\3proxy\doc\ru mkdir dist\3proxy\doc\ru
mkdir dist\3proxy\doc\html mkdir dist\3proxy\doc\html
mkdir dist\3proxy\doc\html\plugins mkdir dist\3proxy\doc\html\plugins
mkdir dist\3proxy\doc\html\man3 mkdir dist\3proxy\doc\html\man5
mkdir dist\3proxy\doc\html\man8 mkdir dist\3proxy\doc\html\man8
mkdir dist\3proxy\doc\devel mkdir dist\3proxy\doc\devel
copy bin\3proxy.exe dist\3proxy\bin\ copy bin\3proxy.exe dist\3proxy\bin\
@ -63,7 +61,7 @@ jobs:
copy doc\html\*.* dist\3proxy\doc\html\ copy doc\html\*.* dist\3proxy\doc\html\
copy doc\html\plugins\*.* dist\3proxy\doc\html\plugins\ copy doc\html\plugins\*.* dist\3proxy\doc\html\plugins\
copy doc\html\man8\*.* dist\3proxy\doc\html\man8\ copy doc\html\man8\*.* dist\3proxy\doc\html\man8\
copy doc\html\man3\*.* dist\3proxy\doc\html\man3\ copy doc\html\man5\*.* dist\3proxy\doc\html\man5\
copy doc\devel\*.rtf dist\3proxy\doc\devel\ copy doc\devel\*.rtf dist\3proxy\doc\devel\
copy copying dist\3proxy\ copy copying dist\3proxy\
copy authors dist\3proxy\ copy authors dist\3proxy\

View File

@ -1,9 +1,7 @@
name: Build Win64 3proxy with MSVC name: Build Win64 3proxy with MSVC
on: on:
push: workflow_dispatch:
branches: [ "master" ]
paths: [ 'RELEASE', '.github/workflows/build-win64.yml' ]
jobs: jobs:
ci: ci:
@ -30,7 +28,6 @@ jobs:
- name: Add msbuild to PATH - name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v3 uses: microsoft/setup-msbuild@v3
- name: make Windows MSVC - name: make Windows MSVC
if: ${{ startsWith(matrix.target, 'windows') }}
shell: cmd shell: cmd
run: | run: |
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
@ -41,6 +38,17 @@ jobs:
echo "volatile char VerSion[]=^"3APA3A-3proxy-Internal-Build: 3proxy-%RELEASE%-%NOW%\r\nCode certificate: https://3proxy.org/3proxy.cer\r\n^";" >>src/3proxy.c echo "volatile char VerSion[]=^"3APA3A-3proxy-Internal-Build: 3proxy-%RELEASE%-%NOW%\r\nCode certificate: https://3proxy.org/3proxy.cer\r\n^";" >>src/3proxy.c
echo %NOW% / %RELEASE% / %BUILDDATE% / %VERSION% echo %NOW% / %RELEASE% / %BUILDDATE% / %VERSION%
nmake /F Makefile.msvc nmake /F Makefile.msvc
- name: Decode Certificate
shell: pwsh
run: |
$pfx_cert_byte = [System.Convert]::FromBase64String("${{ secrets.WINDOWS_CERTIFICATE }}")
[System.IO.File]::WriteAllBytes("${{ github.workspace }}\cert.pfx", $pfx_cert_byte)
- name: Sign
shell: pwsh
run: |
$signtool = (Get-ChildItem "C:\Program Files (x86)\Windows Kits\10\bin\*\x64\signtool.exe" | Sort-Object { [version]$_.Directory.Parent.Name } -Descending | Select-Object -First 1).FullName
& $signtool sign /f "${{ github.workspace }}\cert.pfx" /p "${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}" /tr http://timestamp.digicert.com /td sha256 /fd sha256 "bin\3proxy.exe"
& $signtool sign /f "${{ github.workspace }}\cert.pfx" /p "${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}" /tr http://timestamp.digicert.com /td sha256 /fd sha256 "bin\3proxy_crypt.exe"
- name: make dist dir - name: make dist dir
shell: cmd shell: cmd
run: | run: |
@ -53,19 +61,19 @@ jobs:
mkdir dist\3proxy\doc\ru mkdir dist\3proxy\doc\ru
mkdir dist\3proxy\doc\html mkdir dist\3proxy\doc\html
mkdir dist\3proxy\doc\html\plugins mkdir dist\3proxy\doc\html\plugins
mkdir dist\3proxy\doc\html\man3 mkdir dist\3proxy\doc\html\man5
mkdir dist\3proxy\doc\html\man8 mkdir dist\3proxy\doc\html\man8
mkdir dist\3proxy\doc\devel mkdir dist\3proxy\doc\devel
copy bin\3proxy.exe dist\3proxy\bin64\ copy bin\3proxy.exe dist\3proxy\bin64\
copy bin\*.dll dist\3proxy\bin64\ copy bin\*.dll dist\3proxy\bin64\
copy bin\mycrypt.exe dist\3proxy\bin64\ copy bin\3proxy_crypt.exe dist\3proxy\bin64\
copy cfg\*.* dist\3proxy\cfg\ copy cfg\*.* dist\3proxy\cfg\
copy cfg\sql\*.* dist\3proxy\cfg\sql\ copy cfg\sql\*.* dist\3proxy\cfg\sql\
copy doc\ru\*.* dist\3proxy\doc\ru\ copy doc\ru\*.* dist\3proxy\doc\ru\
copy doc\html\*.* dist\3proxy\doc\html\ copy doc\html\*.* dist\3proxy\doc\html\
copy doc\html\plugins\*.* dist\3proxy\doc\html\plugins\ copy doc\html\plugins\*.* dist\3proxy\doc\html\plugins\
copy doc\html\man8\*.* dist\3proxy\doc\html\man8\ copy doc\html\man8\*.* dist\3proxy\doc\html\man8\
copy doc\html\man3\*.* dist\3proxy\doc\html\man3\ copy doc\html\man5\*.* dist\3proxy\doc\html\man5\
copy doc\devel\*.rtf dist\3proxy\doc\devel\ copy doc\devel\*.rtf dist\3proxy\doc\devel\
copy copying dist\3proxy\ copy copying dist\3proxy\
copy authors dist\3proxy\ copy authors dist\3proxy\

View File

@ -1,9 +1,7 @@
name: Build Win-arm64 3proxy with MSVC name: Build Win-arm64 3proxy with MSVC
on: on:
push: workflow_dispatch:
branches: [ "master" ]
paths: [ 'RELEASE', '.github/workflows/build-winarm64.yml' ]
jobs: jobs:
ci: ci:
@ -51,7 +49,7 @@ jobs:
mkdir dist\3proxy\doc\ru mkdir dist\3proxy\doc\ru
mkdir dist\3proxy\doc\html mkdir dist\3proxy\doc\html
mkdir dist\3proxy\doc\html\plugins mkdir dist\3proxy\doc\html\plugins
mkdir dist\3proxy\doc\html\man3 mkdir dist\3proxy\doc\html\man5
mkdir dist\3proxy\doc\html\man8 mkdir dist\3proxy\doc\html\man8
mkdir dist\3proxy\doc\devel mkdir dist\3proxy\doc\devel
copy bin\3proxy.exe dist\3proxy\bin64\ copy bin\3proxy.exe dist\3proxy\bin64\
@ -63,7 +61,7 @@ jobs:
copy doc\html\*.* dist\3proxy\doc\html\ copy doc\html\*.* dist\3proxy\doc\html\
copy doc\html\plugins\*.* dist\3proxy\doc\html\plugins\ copy doc\html\plugins\*.* dist\3proxy\doc\html\plugins\
copy doc\html\man8\*.* dist\3proxy\doc\html\man8\ copy doc\html\man8\*.* dist\3proxy\doc\html\man8\
copy doc\html\man3\*.* dist\3proxy\doc\html\man3\ copy doc\html\man5\*.* dist\3proxy\doc\html\man5\
copy doc\devel\*.rtf dist\3proxy\doc\devel\ copy doc\devel\*.rtf dist\3proxy\doc\devel\
copy copying dist\3proxy\ copy copying dist\3proxy\
copy authors dist\3proxy\ copy authors dist\3proxy\

View File

@ -7,6 +7,7 @@ on:
pull_request: pull_request:
branches: [ "master" ] branches: [ "master" ]
paths: [ '**.c', '**.h', 'Makefile.Linux', '.github/configs', '.github/workflows/c-cpp-Linux.yml' ] paths: [ '**.c', '**.h', 'Makefile.Linux', '.github/configs', '.github/workflows/c-cpp-Linux.yml' ]
workflow_dispatch:
jobs: jobs:
ci: ci:

View File

@ -7,6 +7,7 @@ on:
pull_request: pull_request:
branches: [ "master" ] branches: [ "master" ]
paths: [ '**.c', '**.h', 'Makefile.FreeBSD', '.github/configs', '.github/workflows/c-cpp-MacOS.yml' ] paths: [ '**.c', '**.h', 'Makefile.FreeBSD', '.github/configs', '.github/workflows/c-cpp-MacOS.yml' ]
workflow_dispatch:
jobs: jobs:
ci: ci:

View File

@ -7,6 +7,7 @@ on:
pull_request: pull_request:
branches: [ "master" ] branches: [ "master" ]
paths: [ '**.c', '**.h', 'Makefile.msvc', '.github/configs', '.github/workflows/c-cpp-Windows.yml' ] paths: [ '**.c', '**.h', 'Makefile.msvc', '.github/configs', '.github/workflows/c-cpp-Windows.yml' ]
workflow_dispatch:
jobs: jobs:
ci: ci:

View File

@ -7,6 +7,7 @@ on:
pull_request: pull_request:
branches: [ "master" ] branches: [ "master" ]
paths: [ '**.c', '**.h', '**.cmake', 'CMakeLists.txt', '.github/configs', '.github/workflows/c-cpp-cmake.yml' ] paths: [ '**.c', '**.h', '**.cmake', 'CMakeLists.txt', '.github/configs', '.github/workflows/c-cpp-cmake.yml' ]
workflow_dispatch:
jobs: jobs:
ci: ci:

9
.gitignore vendored
View File

@ -259,3 +259,12 @@ pip-log.txt
.mr.developer.cfg .mr.developer.cfg
CLAUDE.md CLAUDE.md
bin/3proxy_crypt bin/3proxy_crypt
bin/3proxy_ftppr
bin/3proxy_pop3p
bin/3proxy_proxy
bin/3proxy_smtpp
bin/3proxy_socks
bin/3proxy_tcppm
bin/3proxy_tlspr
bin/3proxy_udppm
build*/*

11
CHANGELOG Normal file
View File

@ -0,0 +1,11 @@
3proxy-0.9.6 Released April, 11 2026
+ ssl_client and multiple configuration options added to SSLPlugin, SSLPlugin code significantly improved and bugfixed. See https://github.com/3proxy/3proxy/wiki/SSLPlugin. 3proxy can now be used as stunnel replacement for many scenarios.
+ HAProxy proxy protocol v1 support as client and server, add -H option for service to expect HA proxy v1 protocol header, use ha parent type: parent 1000 ha 0.0.0.0 0 to send v1 header.
+ tlspr is supported in auto
+ tlspr supports -s option, it breaks HELLO packet to prevent some DPIs from detecting SNI
+ maxseg configuration option and TCP_MAXSEG socket flag support added. It sets maximum size of TCP segment to fix PathMTU discovery problems
+ -Ne / -Ni options added to specify external / internal NAT address for SOCKSv5
+ cmake environment added
! External pcre2 (pcre2-8) library is used for PCRE, pcre code is removed from 3proxy
! Multiple minor bugfixes

11
CHANGELOG.rus Normal file
View File

@ -0,0 +1,11 @@
3proxy-0.9.6 Вышел 11 Апреля 2026
+ В SSLPlugin добавлены ssl_client и множество опций конфигурации, код SSLPlugin значительно улучшен и исправлен. См. https://github.com/3proxy/3proxy/wiki/SSLPlugin. 3proxy теперь может использоваться как замена stunnel во многих сценариях.
+ Поддержка прокси-протокола HAProxy v1 на стороне клиента и сервера. Добавлена опция -H для сервиса, чтобы ожидать заголовок прокси-протокола HA v1. Используйте тип родителя ha: parent 1000 ha 0.0.0.0 0 для отправки заголовка v1.
+ tlspr поддерживается в режиме auto
+ tlspr поддерживает опцию -s, которая разбивает HELLO-пакет для предотвращения обнаружения SNI некоторыми DPI
+ Добавлена опция конфигурации maxseg и поддержка флага сокета TCP_MAXSEG. Устанавливает максимальный размер TCP-сегмента для решения проблем с обнаружением PathMTU
+ Добавлены опции -Ne / -Ni для указания внешнего/внутреннего NAT-адреса для SOCKSv5
+ Добавлено окружение cmake
! Внешняя библиотека pcre2 (pcre2-8) используется для PCRE, код pcre удалён из 3proxy
! Множество мелких исправлений ошибок

View File

@ -46,8 +46,8 @@ endif()
# Options # Options
option(3PROXY_BUILD_SHARED "Build shared libraries for plugins" ON) option(3PROXY_BUILD_SHARED "Build shared libraries for plugins" ON)
option(3PROXY_USE_OPENSSL "Enable OpenSSL/SSLPlugin" ON) option(3PROXY_USE_OPENSSL "Enable TLS/SSL support (requires OpenSSL)" ON)
option(3PROXY_USE_PCRE2 "Enable PCRE2/PCREPlugin" ON) option(3PROXY_USE_PCRE2 "Enable PCRE2 regex filtering" ON)
option(3PROXY_USE_PAM "Enable PAM/PamAuth" ON) option(3PROXY_USE_PAM "Enable PAM/PamAuth" ON)
option(3PROXY_USE_ODBC "Enable ODBC support (Unix only, always ON on Windows)" OFF) option(3PROXY_USE_ODBC "Enable ODBC support (Unix only, always ON on Windows)" OFF)
option(3PROXY_USE_SPLICE "Use Linux splice() for zero-copy (Linux only)" ON) option(3PROXY_USE_SPLICE "Use Linux splice() for zero-copy (Linux only)" ON)
@ -56,6 +56,31 @@ option(3PROXY_USE_WSAPOLL "Use WSAPoll instead of select() (Windows only)" ON)
option(3PROXY_USE_NETFILTER "Enable Linux netfilter support (Linux only)" ON) option(3PROXY_USE_NETFILTER "Enable Linux netfilter support (Linux only)" ON)
option(3PROXY_USE_UNIX_SOCKETS "Enable Unix domain socket support (Unix only)" ON) option(3PROXY_USE_UNIX_SOCKETS "Enable Unix domain socket support (Unix only)" ON)
if(NOT WIN32 AND NOT APPLE)
option(3PROXY_STATIC_LINK "Statically link libraries using -Wl,-Bstatic (Linux/Unix only)" OFF)
endif()
# Binary name prefix for standalone modules and crypt (default: 3proxy_)
# For crypt: if prefix is empty, "my" is used instead ( mycrypt)
set(3PROXY_BINARY_PREFIX "3proxy_" CACHE STRING "Prefix for standalone module and crypt binary names")
# Standalone module build options (OFF by default)
option(3PROXY_BUILD_ALL "Build all standalone binaries" OFF)
option(3PROXY_BUILD_PROXY "Build standalone proxy binary" OFF)
option(3PROXY_BUILD_SOCKS "Build standalone socks binary" OFF)
option(3PROXY_BUILD_POP3P "Build standalone pop3p binary" OFF)
option(3PROXY_BUILD_SMTPP "Build standalone smtpp binary" OFF)
option(3PROXY_BUILD_FTPPR "Build standalone ftppr binary" OFF)
option(3PROXY_BUILD_TCPPM "Build standalone tcppm binary" OFF)
option(3PROXY_BUILD_UDPPM "Build standalone udppm binary" OFF)
option(3PROXY_BUILD_TLSPR "Build standalone tlspr binary" OFF)
if(3PROXY_BUILD_ALL)
foreach(_M PROXY SOCKS POP3P SMTPP FTPPR TCPPM UDPPM TLSPR)
set(3PROXY_BUILD_${_M} ON)
endforeach()
endif()
# Output directory # Output directory
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
@ -84,7 +109,6 @@ if(WIN32)
# MSVC-specific settings # MSVC-specific settings
add_compile_definitions( add_compile_definitions(
MSVC MSVC
WITH_SSL
) )
# Use static runtime library # Use static runtime library
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>") set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
@ -102,7 +126,6 @@ if(WIN32)
# clang-cl (Clang with MSVC frontend) # clang-cl (Clang with MSVC frontend)
add_compile_definitions( add_compile_definitions(
MSVC MSVC
WITH_SSL
) )
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>") set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
add_compile_options( add_compile_options(
@ -233,14 +256,14 @@ endif()
# OpenSSL # OpenSSL
set(OPENSSL_FOUND FALSE) set(OPENSSL_FOUND FALSE)
if(3PROXY_USE_OPENSSL) if(3PROXY_USE_OPENSSL)
find_package(OpenSSL QUIET) find_package(OpenSSL REQUIRED)
if(OpenSSL_FOUND) if(OpenSSL_FOUND)
set(OPENSSL_FOUND TRUE) set(OPENSSL_FOUND TRUE)
add_compile_definitions(WITH_SSL) add_compile_definitions(WITH_SSL)
message(STATUS "OpenSSL found: ${OPENSSL_VERSION}") message(STATUS "OpenSSL found: ${OPENSSL_VERSION}")
else()
message(STATUS "OpenSSL not found, SSLPlugin will not be built")
endif() endif()
else()
message(STATUS "OpenSSL disabled by user request")
endif() endif()
# PCRE2 # PCRE2
@ -248,9 +271,10 @@ set(PCRE2_FOUND FALSE)
if(3PROXY_USE_PCRE2) if(3PROXY_USE_PCRE2)
find_package(PCRE2 QUIET) find_package(PCRE2 QUIET)
if(PCRE2_FOUND) if(PCRE2_FOUND)
add_compile_definitions(WITH_PCRE)
message(STATUS "PCRE2 found: ${PCRE2_VERSION}") message(STATUS "PCRE2 found: ${PCRE2_VERSION}")
else() else()
message(STATUS "PCRE2 not found, PCREPlugin will not be built") message(STATUS "PCRE2 not found, PCRE support will not be built")
endif() endif()
endif() endif()
@ -276,17 +300,26 @@ if(WIN32 OR 3PROXY_USE_ODBC)
endif() endif()
endif() endif()
# Set NOODBC if ODBC is not found # Define WITH_ODBC when ODBC is available
if(NOT ODBC_FOUND) if(ODBC_FOUND)
add_compile_definitions(NOODBC) add_compile_definitions(WITH_ODBC)
endif()
# Set NORADIUS if OpenSSL is not available (RADIUS requires MD5 from OpenSSL)
if(NOT OPENSSL_FOUND)
add_compile_definitions(NORADIUS)
endif() endif()
# Source files for 3proxy core # Source files for 3proxy core
set(3PROXY_CORE_SOURCES set(3PROXY_CORE_SOURCES
src/3proxy.c src/3proxy.c
src/auth.c src/auth.c
src/acl.c
src/limiter.c
src/redirect.c
src/authradius.c src/authradius.c
src/hash.c src/hash.c
src/hashtables.c
src/resolve.c src/resolve.c
src/sql.c src/sql.c
src/conf.c src/conf.c
@ -295,10 +328,8 @@ set(3PROXY_CORE_SOURCES
src/stringtable.c src/stringtable.c
) )
# MD4/MD5/BLAKE2 sources for 3proxy_crypt # BLAKE2 source for 3proxy_crypt
set(MD_SOURCES set(MD_SOURCES
src/libs/md4.c
src/libs/md5.c
src/libs/blake2b-ref.c src/libs/blake2b-ref.c
) )
@ -324,7 +355,7 @@ target_include_directories(base64_obj PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
# These are used by the main 3proxy executable # These are used by the main 3proxy executable
# ============================================================================ # ============================================================================
# Server modules object library (without WITHMAIN) # Server modules object library (without WITHMAIN, without UDP)
add_library(srv_modules OBJECT add_library(srv_modules OBJECT
src/proxy.c src/proxy.c
src/pop3p.c src/pop3p.c
@ -335,13 +366,21 @@ add_library(srv_modules OBJECT
src/auto.c src/auto.c
src/socks.c src/socks.c
src/webadmin.c src/webadmin.c
src/udppm.c
src/dnspr.c src/dnspr.c
) )
target_include_directories(srv_modules PRIVATE target_include_directories(srv_modules PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src ${CMAKE_CURRENT_SOURCE_DIR}/src
) )
# UDP port mapper server module (without WITHMAIN)
add_library(srvudppm_obj OBJECT src/udppm.c)
target_include_directories(srvudppm_obj PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src
)
# UDP socket relay (used by 3proxy, socks, udppm)
add_library(udpsockmap_obj OBJECT src/udpsockmap.c)
target_include_directories(udpsockmap_obj PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
# mainfunc object (proxymain.c compiled with MODULEMAINFUNC=mainfunc for 3proxy) # mainfunc object (proxymain.c compiled with MODULEMAINFUNC=mainfunc for 3proxy)
add_library(mainfunc OBJECT src/proxymain.c) add_library(mainfunc OBJECT src/proxymain.c)
@ -355,6 +394,9 @@ target_include_directories(ftp_obj PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
# 3proxy_crypt object for 3proxy (without WITHMAIN) # 3proxy_crypt object for 3proxy (without WITHMAIN)
add_library(3proxy_crypt_obj OBJECT src/3proxy_crypt.c) add_library(3proxy_crypt_obj OBJECT src/3proxy_crypt.c)
target_include_directories(3proxy_crypt_obj PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) target_include_directories(3proxy_crypt_obj PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
if(OpenSSL_FOUND)
target_include_directories(3proxy_crypt_obj PRIVATE ${OPENSSL_INCLUDE_DIR})
endif()
# ============================================================================ # ============================================================================
# Main 3proxy executable # Main 3proxy executable
@ -363,19 +405,35 @@ target_include_directories(3proxy_crypt_obj PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/
add_executable(3proxy add_executable(3proxy
${3PROXY_CORE_SOURCES} ${3PROXY_CORE_SOURCES}
${MD_SOURCES}
$<TARGET_OBJECTS:srv_modules> $<TARGET_OBJECTS:srv_modules>
$<TARGET_OBJECTS:srvudppm_obj>
$<TARGET_OBJECTS:mainfunc> $<TARGET_OBJECTS:mainfunc>
$<TARGET_OBJECTS:common_obj> $<TARGET_OBJECTS:common_obj>
$<TARGET_OBJECTS:udpsockmap_obj>
$<TARGET_OBJECTS:base64_obj> $<TARGET_OBJECTS:base64_obj>
$<TARGET_OBJECTS:ftp_obj> $<TARGET_OBJECTS:ftp_obj>
$<TARGET_OBJECTS:3proxy_crypt_obj> $<TARGET_OBJECTS:3proxy_crypt_obj>
) )
target_sources(3proxy PRIVATE ${MD_SOURCES})
if(OpenSSL_FOUND)
target_sources(3proxy PRIVATE src/ssllib.c src/ssl.c)
endif()
if(PCRE2_FOUND)
target_sources(3proxy PRIVATE src/pcre.c)
endif()
target_include_directories(3proxy PRIVATE target_include_directories(3proxy PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src ${CMAKE_CURRENT_SOURCE_DIR}/src
${CMAKE_CURRENT_SOURCE_DIR}/src/libs ${CMAKE_CURRENT_SOURCE_DIR}/src/libs
) )
if(OpenSSL_FOUND)
target_include_directories(3proxy PRIVATE ${OPENSSL_INCLUDE_DIR})
endif()
if(PCRE2_FOUND)
target_include_directories(3proxy PRIVATE ${PCRE2_INCLUDE_DIRS})
endif()
target_link_libraries(3proxy PRIVATE Threads::Threads) target_link_libraries(3proxy PRIVATE Threads::Threads)
@ -387,36 +445,123 @@ if(ODBC_FOUND)
endif() endif()
endif() endif()
if(WIN32) # OpenSSL linking
target_link_libraries(3proxy PRIVATE ${WINDOWS_LIBS}) if(OpenSSL_FOUND)
if(OpenSSL_FOUND) if(3PROXY_STATIC_LINK)
# Will be linked statically below (if static libraries are found)
else()
target_link_libraries(3proxy PRIVATE OpenSSL::SSL OpenSSL::Crypto) target_link_libraries(3proxy PRIVATE OpenSSL::SSL OpenSSL::Crypto)
endif() endif()
endif()
# PCRE2 linking
if(PCRE2_FOUND)
if(3PROXY_STATIC_LINK)
# Will be linked statically below (if static libraries are found)
elseif(TARGET PCRE2::PCRE2)
target_link_libraries(3proxy PRIVATE PCRE2::PCRE2)
else()
target_link_libraries(3proxy PRIVATE ${PCRE2_LIBRARIES})
endif()
endif()
# Static linking of OpenSSL and PCRE2 (when option is enabled)
if(3PROXY_STATIC_LINK AND (OpenSSL_FOUND OR PCRE2_FOUND))
set(_saved_cmake_find_library_suffixes ${CMAKE_FIND_LIBRARY_SUFFIXES})
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
set(_static_libs "")
if(OpenSSL_FOUND)
find_library(_ssl_static_lib ssl)
find_library(_crypto_static_lib crypto)
if(_ssl_static_lib AND _crypto_static_lib)
list(APPEND _static_libs ${_ssl_static_lib} ${_crypto_static_lib})
endif()
endif()
if(PCRE2_FOUND)
find_library(_pcre2_static_lib NAMES pcre2-8)
if(_pcre2_static_lib)
list(APPEND _static_libs ${_pcre2_static_lib})
endif()
endif()
set(CMAKE_FIND_LIBRARY_SUFFIXES ${_saved_cmake_find_library_suffixes})
if(_static_libs)
target_link_libraries(3proxy PRIVATE -Wl,-Bstatic ${_static_libs} -Wl,-Bdynamic)
message(STATUS "Static linking enabled for OpenSSL/PCRE2")
else()
message(WARNING "3PROXY_STATIC_LINK is ON but static libraries not found, falling back to dynamic")
if(OpenSSL_FOUND)
target_link_libraries(3proxy PRIVATE OpenSSL::SSL OpenSSL::Crypto)
endif()
if(PCRE2_FOUND)
if(TARGET PCRE2::PCRE2)
target_link_libraries(3proxy PRIVATE PCRE2::PCRE2)
else()
target_link_libraries(3proxy PRIVATE ${PCRE2_LIBRARIES})
endif()
endif()
endif()
endif()
if(WIN32)
target_link_libraries(3proxy PRIVATE ${WINDOWS_LIBS})
if(COMPILER_IS_MSVC AND EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/3proxy.rc) if(COMPILER_IS_MSVC AND EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/3proxy.rc)
target_sources(3proxy PRIVATE 3proxy.rc) target_sources(3proxy PRIVATE 3proxy.rc)
endif() endif()
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
target_link_libraries(3proxy PRIVATE dl) target_link_libraries(3proxy PRIVATE dl)
if(OpenSSL_FOUND)
target_link_libraries(3proxy PRIVATE OpenSSL::SSL OpenSSL::Crypto)
endif()
endif() endif()
# Build 3proxy_crypt utility # Build 3proxy_crypt utility
add_executable(3proxy_crypt add_executable(3proxy_crypt
src/3proxy_crypt.c src/3proxy_crypt.c
${MD_SOURCES}
$<TARGET_OBJECTS:base64_obj> $<TARGET_OBJECTS:base64_obj>
) )
target_sources(3proxy_crypt PRIVATE ${MD_SOURCES})
target_compile_definitions(3proxy_crypt PRIVATE WITHMAIN) target_compile_definitions(3proxy_crypt PRIVATE WITHMAIN)
target_include_directories(3proxy_crypt PRIVATE target_include_directories(3proxy_crypt PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src ${CMAKE_CURRENT_SOURCE_DIR}/src
${CMAKE_CURRENT_SOURCE_DIR}/src/libs ${CMAKE_CURRENT_SOURCE_DIR}/src/libs
) )
if(OpenSSL_FOUND)
target_include_directories(3proxy_crypt PRIVATE ${OPENSSL_INCLUDE_DIR})
endif()
target_link_libraries(3proxy_crypt PRIVATE Threads::Threads) target_link_libraries(3proxy_crypt PRIVATE Threads::Threads)
if(OpenSSL_FOUND)
if(3PROXY_STATIC_LINK)
set(_saved_cmake_find_library_suffixes ${CMAKE_FIND_LIBRARY_SUFFIXES})
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
find_library(_ssl_static_lib ssl)
find_library(_crypto_static_lib crypto)
set(CMAKE_FIND_LIBRARY_SUFFIXES ${_saved_cmake_find_library_suffixes})
if(_ssl_static_lib AND _crypto_static_lib)
target_link_libraries(3proxy_crypt PRIVATE -Wl,-Bstatic ${_ssl_static_lib} ${_crypto_static_lib} -Wl,-Bdynamic)
message(STATUS "3proxy_crypt: static OpenSSL")
else()
message(WARNING "3PROXY_STATIC_LINK is ON but static OpenSSL not found, using dynamic")
target_link_libraries(3proxy_crypt PRIVATE OpenSSL::SSL OpenSSL::Crypto)
endif()
else()
target_link_libraries(3proxy_crypt PRIVATE OpenSSL::SSL OpenSSL::Crypto)
endif()
endif()
if("${3PROXY_BINARY_PREFIX}" STREQUAL "")
set_target_properties(3proxy_crypt PROPERTIES OUTPUT_NAME "mycrypt")
else()
set_target_properties(3proxy_crypt PROPERTIES OUTPUT_NAME "${3PROXY_BINARY_PREFIX}crypt")
endif()
# Build standalone proxy executables # Build standalone proxy executables
foreach(PROXY_NAME proxy socks pop3p smtpp ftppr tcppm udppm tlspr) foreach(PROXY_NAME proxy socks pop3p smtpp ftppr tcppm udppm tlspr)
string(TOUPPER "${PROXY_NAME}" _MODULE_OPT)
if(NOT 3PROXY_BUILD_${_MODULE_OPT})
continue()
endif()
if(PROXY_NAME STREQUAL "ftppr" OR PROXY_NAME STREQUAL "proxy") if(PROXY_NAME STREQUAL "ftppr" OR PROXY_NAME STREQUAL "proxy")
# ftppr and proxy use ftp_obj # ftppr and proxy use ftp_obj
add_executable(${PROXY_NAME} add_executable(${PROXY_NAME}
@ -431,6 +576,10 @@ foreach(PROXY_NAME proxy socks pop3p smtpp ftppr tcppm udppm tlspr)
) )
endif() endif()
set_target_properties(${PROXY_NAME} PROPERTIES
OUTPUT_NAME "${3PROXY_BINARY_PREFIX}${PROXY_NAME}"
)
target_include_directories(${PROXY_NAME} PRIVATE target_include_directories(${PROXY_NAME} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src ${CMAKE_CURRENT_SOURCE_DIR}/src
) )
@ -440,6 +589,10 @@ foreach(PROXY_NAME proxy socks pop3p smtpp ftppr tcppm udppm tlspr)
NOPORTMAP NOPORTMAP
) )
if(NOT PROXY_NAME STREQUAL "udppm")
target_compile_definitions(${PROXY_NAME} PRIVATE NOUDPMAIN)
endif()
target_link_libraries(${PROXY_NAME} PRIVATE Threads::Threads) target_link_libraries(${PROXY_NAME} PRIVATE Threads::Threads)
if(PROXY_NAME STREQUAL "proxy") if(PROXY_NAME STREQUAL "proxy")
@ -457,6 +610,14 @@ foreach(PROXY_NAME proxy socks pop3p smtpp ftppr tcppm udppm tlspr)
if(PROXY_NAME STREQUAL "proxy" OR PROXY_NAME STREQUAL "smtpp") if(PROXY_NAME STREQUAL "proxy" OR PROXY_NAME STREQUAL "smtpp")
target_sources(${PROXY_NAME} PRIVATE $<TARGET_OBJECTS:base64_obj>) target_sources(${PROXY_NAME} PRIVATE $<TARGET_OBJECTS:base64_obj>)
endif() endif()
if(PROXY_NAME STREQUAL "udppm")
target_sources(${PROXY_NAME} PRIVATE src/hash.c)
endif()
if(PROXY_NAME STREQUAL "socks" OR PROXY_NAME STREQUAL "udppm")
target_sources(${PROXY_NAME} PRIVATE src/udpsockmap.c)
endif()
endforeach() endforeach()
# Plugin output directory # Plugin output directory
@ -475,35 +636,30 @@ foreach(PLUGIN ${DEFAULT_PLUGINS})
add_subdirectory(src/plugins/${PLUGIN}) add_subdirectory(src/plugins/${PLUGIN})
endforeach() endforeach()
if(OPENSSL_FOUND)
add_subdirectory(src/plugins/SSLPlugin)
endif()
if(PCRE2_FOUND)
add_subdirectory(src/plugins/PCREPlugin)
endif()
if(PAM_FOUND) if(PAM_FOUND)
add_subdirectory(src/plugins/PamAuth) add_subdirectory(src/plugins/PamAuth)
endif() endif()
# Build full list of plugins to be built # Build full list of plugins to be built
set(ALL_PLUGINS ${DEFAULT_PLUGINS}) set(ALL_PLUGINS ${DEFAULT_PLUGINS})
if(OPENSSL_FOUND)
list(APPEND ALL_PLUGINS SSLPlugin)
endif()
if(PCRE2_FOUND)
list(APPEND ALL_PLUGINS PCREPlugin)
endif()
if(PAM_FOUND) if(PAM_FOUND)
list(APPEND ALL_PLUGINS PamAuth) list(APPEND ALL_PLUGINS PamAuth)
endif() endif()
# Installation rules # Installation rules
install(TARGETS 3proxy 3proxy_crypt proxy socks pop3p smtpp ftppr tcppm udppm tlspr install(TARGETS 3proxy 3proxy_crypt
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
) )
foreach(PROXY_NAME proxy socks pop3p smtpp ftppr tcppm udppm tlspr)
string(TOUPPER "${PROXY_NAME}" _MODULE_OPT)
if(3PROXY_BUILD_${_MODULE_OPT})
install(TARGETS ${PROXY_NAME}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
endif()
endforeach()
# Install plugins # Install plugins
file(GLOB PLUGINFILES "${PLUGIN_OUTPUT_DIR}/*${PLUGIN_SUFFIX}") file(GLOB PLUGINFILES "${PLUGIN_OUTPUT_DIR}/*${PLUGIN_SUFFIX}")
if(WIN32) if(WIN32)
@ -637,10 +793,32 @@ endif()
# Install man pages # Install man pages
if(NOT WIN32) if(NOT WIN32)
file(GLOB MAN3_FILES "${CMAKE_CURRENT_SOURCE_DIR}/man/*.3") # Config man page (section 5) no prefix
file(GLOB MAN8_FILES "${CMAKE_CURRENT_SOURCE_DIR}/man/*.8") file(GLOB MAN5_FILES "${CMAKE_CURRENT_SOURCE_DIR}/man/*.5")
install(FILES ${MAN3_FILES} DESTINATION ${CMAKE_INSTALL_MANDIR}/man3) install(FILES ${MAN5_FILES} DESTINATION ${CMAKE_INSTALL_MANDIR}/man5)
install(FILES ${MAN8_FILES} DESTINATION ${CMAKE_INSTALL_MANDIR}/man8) # Main 3proxy man page no prefix
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/man/3proxy.8"
DESTINATION ${CMAKE_INSTALL_MANDIR}/man8
)
# 3proxy_crypt man page no prefix (already has 3proxy_)
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/man/3proxy_crypt.8")
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/man/3proxy_crypt.8"
DESTINATION ${CMAKE_INSTALL_MANDIR}/man8
)
endif()
# Module man pages installed with binary prefix only if module is built
foreach(_MAN proxy socks pop3p 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")
if(EXISTS "${_MAN_SRC}")
install(FILES "${_MAN_SRC}"
DESTINATION ${CMAKE_INSTALL_MANDIR}/man8
RENAME "${3PROXY_BINARY_PREFIX}${_MAN}.8"
)
endif()
endif()
endforeach()
endif() endif()
# Summary # Summary
@ -662,6 +840,9 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
message(STATUS " USE_SPLICE: ${3PROXY_USE_SPLICE}") message(STATUS " USE_SPLICE: ${3PROXY_USE_SPLICE}")
message(STATUS " USE_NETFILTER: ${3PROXY_USE_NETFILTER}") message(STATUS " USE_NETFILTER: ${3PROXY_USE_NETFILTER}")
endif() endif()
if(NOT WIN32 AND NOT APPLE)
message(STATUS " STATIC_LINK: ${3PROXY_STATIC_LINK}")
endif()
if(WIN32) if(WIN32)
message(STATUS " USE_WSAPOLL: ${3PROXY_USE_WSAPOLL}") message(STATUS " USE_WSAPOLL: ${3PROXY_USE_WSAPOLL}")
endif() endif()
@ -674,3 +855,10 @@ message(STATUS " ODBC: ${ODBC_FOUND}")
message(STATUS "") message(STATUS "")
message(STATUS " Plugins to build: ${ALL_PLUGINS}") message(STATUS " Plugins to build: ${ALL_PLUGINS}")
message(STATUS "") message(STATUS "")
message(STATUS " Standalone modules:")
message(STATUS " Binary prefix: \"${3PROXY_BINARY_PREFIX}\"")
foreach(_M proxy socks pop3p smtpp ftppr tcppm udppm tlspr)
string(TOUPPER "${_M}" _MO)
message(STATUS " BUILD_${_MO}: ${3PROXY_BUILD_${_MO}}")
endforeach()
message(STATUS "")

View File

@ -13,7 +13,7 @@
# use "log" without pathname in config to log to stdout. # use "log" without pathname in config to log to stdout.
# plugins are located in /usr/local/3proxy/libexec (/libexec for chroot config) # plugins are located in /usr/local/3proxy/libexec (/libexec for chroot config)
# symlinked as /lib and /lib64 in both root and chroot configurations, so no need # symlinked as /lib and /lib64 in both root and chroot configurations, so no need
# to specify full path to plugin. SSLPlugin is supported. # to specify full path to plugin.
# #
# Since 0.9.6 image is distroless, no reason to use chroot, chroot # Since 0.9.6 image is distroless, no reason to use chroot, chroot
# configuration is supported for compatibility only. # configuration is supported for compatibility only.
@ -23,7 +23,7 @@ FROM docker.io/gcc AS buildenv
COPY . 3proxy COPY . 3proxy
RUN cd 3proxy &&\ RUN cd 3proxy &&\
apt --assume-yes update && apt --assume-yes install libssl-dev libpcre2-dev &&\ apt --assume-yes update && apt --assume-yes install libssl-dev libpcre2-dev &&\
make -f Makefile.Linux &&\ make -f Makefile.Linux LIBSTATIC=true PAM_CHECK=false &&\
strip bin/3proxy &&\ strip bin/3proxy &&\
strip bin/*so &&\ strip bin/*so &&\
mkdir /dist &&\ mkdir /dist &&\
@ -41,14 +41,10 @@ RUN cd 3proxy &&\
RUN cd /dist &&\ RUN cd /dist &&\
ln -s /lib lib64 &&\ ln -s /lib lib64 &&\
ln -s /lib usr/lib &&\ ln -s /lib usr/lib &&\
ln -s /lib usr/lib64 &&\ ln -s /lib usr/lib64
cp /lib64/ld-*.so.* /dist/usr/local/3proxy/libexec &&\ RUN cp /lib/ld-*.so.* /dist/usr/local/3proxy/libexec || true
cp "/lib/`gcc -dumpmachine`"/libdl.so.* /dist/usr/local/3proxy/libexec &&\ RUN cp /lib64/ld-*.so.* /dist/usr/local/3proxy/libexec || true
cp "/lib/`gcc -dumpmachine`"/libcrypto.so.* /dist/usr/local/3proxy/libexec &&\ RUN cp "/lib/`gcc -dumpmachine`"/libdl.so.* /dist/usr/local/3proxy/libexec &&\
cp "/lib/`gcc -dumpmachine`"/libssl.so.* /dist/usr/local/3proxy/libexec &&\
cp "/lib/`gcc -dumpmachine`"/libpcre2-8.so.* /dist/usr/local/3proxy/libexec &&\
cp "/lib/`gcc -dumpmachine`"/libz.so.* /dist/usr/local/3proxy/libexec &&\
cp "/lib/`gcc -dumpmachine`"/libzstd.so.* /dist/usr/local/3proxy/libexec &&\
ls -lR /dist ls -lR /dist
FROM docker.io/busybox:glibc FROM docker.io/busybox:glibc

View File

@ -13,7 +13,7 @@
# use "log" without pathname in config to log to stdout. # use "log" without pathname in config to log to stdout.
# plugins are located in /usr/local/3proxy/libexec (/libexec for chroot config) # plugins are located in /usr/local/3proxy/libexec (/libexec for chroot config)
# symlinked as /lib and /lib64 in both root and chroot configurations, so no need # symlinked as /lib and /lib64 in both root and chroot configurations, so no need
# to specify full path to plugin. SSLPlugin is supported. # to specify full path to plugin.
# #
# Since 0.9.6 image is distroless, no reason to use chroot, chroot # Since 0.9.6 image is distroless, no reason to use chroot, chroot
# configuration is supported for compatibility only. # configuration is supported for compatibility only.
@ -23,7 +23,7 @@ FROM docker.io/gcc AS buildenv
COPY . 3proxy COPY . 3proxy
RUN cd 3proxy &&\ RUN cd 3proxy &&\
apt --assume-yes update && apt --assume-yes install libssl-dev libpcre2-dev &&\ apt --assume-yes update && apt --assume-yes install libssl-dev libpcre2-dev &&\
make -f Makefile.Linux &&\ make -f Makefile.Linux LIBSTATIC=true PAM_CHECK=false &&\
strip bin/3proxy &&\ strip bin/3proxy &&\
mkdir /dist &&\ mkdir /dist &&\
mkdir /dist/etc &&\ mkdir /dist/etc &&\
@ -42,15 +42,11 @@ RUN cd /dist &&\
ln -s /usr/local/3proxy/libexec lib &&\ ln -s /usr/local/3proxy/libexec lib &&\
ln -s /usr/local/3proxy/libexec usr/lib &&\ ln -s /usr/local/3proxy/libexec usr/lib &&\
ln -s /usr/local/3proxy/libexec usr/lib64 &&\ ln -s /usr/local/3proxy/libexec usr/lib64 &&\
ln -s /usr/local/3proxy/libexec /dist/usr/local/3proxy/libexec/`gcc -dumpmachine` &&\ ln -s /usr/local/3proxy/libexec /dist/usr/local/3proxy/libexec/`gcc -dumpmachine`
cp /lib64/ld-*.so.* /dist/usr/local/3proxy/libexec &&\ RUN cp /lib/ld-*.so.* /dist/usr/local/3proxy/libexec || true
cp "/lib/`gcc -dumpmachine`"/libc.so.* /dist/usr/local/3proxy/libexec &&\ RUN cp /lib64/ld-*.so.* /dist/usr/local/3proxy/libexec || true
cp "/lib/`gcc -dumpmachine`"/libdl.so.* /dist/usr/local/3proxy/libexec &&\ RUN cp "/lib/`gcc -dumpmachine`"/libc.so.* /dist/usr/local/3proxy/libexec &&\
cp "/lib/`gcc -dumpmachine`"/libcrypto.so.* /dist/usr/local/3proxy/libexec &&\ cp "/lib/`gcc -dumpmachine`"/libdl.so.* /dist/usr/local/3proxy/libexec
cp "/lib/`gcc -dumpmachine`"/libssl.so.* /dist/usr/local/3proxy/libexec &&\
cp "/lib/`gcc -dumpmachine`"/libpcre2-8.so.* /dist/usr/local/3proxy/libexec &&\
cp "/lib/`gcc -dumpmachine`"/libz.so.* /dist/usr/local/3proxy/libexec &&\
cp "/lib/`gcc -dumpmachine`"/libzstd.so.* /dist/usr/local/3proxy/libexec
RUN cd /dist/usr/local/3proxy/ &&\ RUN cd /dist/usr/local/3proxy/ &&\
ln -s libexec lib &&\ ln -s libexec lib &&\
ln -s libexec lib64 &&\ ln -s libexec lib64 &&\

View File

@ -6,7 +6,7 @@
# This is busybox based docker with only 3proxy static executable. # This is busybox based docker with only 3proxy static executable.
# #
# Limitations for minimal version: # Limitations for minimal version:
# no support for plugins, IPv6, RADIUS, system resolver. # no support for plugins and system resolver.
# 'nserver' or 'fakeresolve' are mandatory in configuration. # 'nserver' or 'fakeresolve' are mandatory in configuration.
# #
# Build: # Build:
@ -28,9 +28,7 @@
FROM docker.io/gcc AS buildenv FROM docker.io/gcc AS buildenv
COPY . 3proxy COPY . 3proxy
RUN cd 3proxy &&\ RUN cd 3proxy &&\
export "LDFLAGS=-static" &&\ make -f Makefile.Linux STATIC=true &&\
export "CFLAGS=-DNOPLUGINS -DNORADIUS -DNOIPV6 -DNOODBC -DNOCRYPT -DNOSTDRESOLVE" &&\
make -f Makefile.Linux PLUGINS= LIBS= &&\
strip bin/3proxy strip bin/3proxy
FROM scratch FROM scratch

View File

@ -1,15 +1,20 @@
# #
# 3 proxy Makefile for GCC/Unix # 3 proxy Makefile for GCC/Unix
# #
# remove -DNOODBC from CFLAGS and add -lodbc to LDFLAGS to compile with ODBC # add -DWITH_ODBC to CFLAGS and -lodbc to LDFLAGS to compile with ODBC
# library support. Add -DSAFESQL for poorely written ODBC library / drivers. # library support. Add -DSAFESQL for poorely written ODBC library / drivers.
BUILDDIR = ../bin/ BUILDDIR = ../bin/
PREFIX ?= 3proxy_
CRYPT_PREFIX ?= $(PREFIX)
MANDIR ?= /usr/share/man
CC ?= cc CC ?= cc
CFLAGS := -c -fno-strict-aliasing -DNOODBC -DFD_SETSIZE=4096 -DWITH_POLL -DWITH_UN $(CFLAGS) CFLAGS ?= -O3 -flto
CFLAGS += -c -fno-strict-aliasing -DFD_SETSIZE=4096 -DWITH_POLL -DWITH_UN
COUT = -o COUT = -o
LN ?= ${CC} LN ?= ${CC}
LDFLAGS ?= -O3 -flto
LDFLAGS += -pthread -fno-strict-aliasing LDFLAGS += -pthread -fno-strict-aliasing
# -lpthreads may be reuiured on some platforms instead of -pthreads # -lpthreads may be reuiured on some platforms instead of -pthreads
# -ldl or -lld may be required for some platforms # -ldl or -lld may be required for some platforms
@ -30,16 +35,33 @@ TYPECOMMAND = cat
COMPATLIBS = COMPATLIBS =
MAKEFILE = Makefile.FreeBSD MAKEFILE = Makefile.FreeBSD
PLUGINS ?= StringsPlugin TrafficPlugin TransparentPlugin FilePlugin PLUGINS ?= StringsPlugin TrafficPlugin TransparentPlugin FilePlugin
OPENSSL_CHECK = $(shell echo "\#include <openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestssl testssl.o -lcrypto -lssl 2>/dev/null && rm testssl testssl.o && echo true||echo false) ifeq ($(STATIC), true)
LDFLAGS += -static
CFLAGS += -DNOPLUGINS -DNOSTDRESOLVE -DNOCRYPT
ZLIB = -lz -lzstd
PLUGINS =
PAM_CHECK = false
endif
ifeq ($(LIBSTATIC), true)
STATIC_PREFIX = -Wl,-Bstatic
STATIC_SUFFIX = -Wl,-Bdynamic
ZLIB = -lz -lzstd
endif
OPENSSL_CHECK ?= $(shell echo "\#include <openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestssl testssl.o $(STATIC_PREFIX) $(ZLIB) -lcrypto -lssl $(STATIC_SUFFIX) 2>/dev/null && rm testssl testssl.o && echo true||echo false)
ifeq ($(OPENSSL_CHECK), true) ifeq ($(OPENSSL_CHECK), true)
LIBS += -l crypto -l ssl LIBS += $(STATIC_PREFIX) $(ZLIB) -l crypto -l ssl $(STATIC_SUFFIX)
PLUGINS += SSLPlugin CFLAGS += -DWITH_SSL
SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS)
else
ZLIB :=
endif endif
PCRE_CHECK = $(shell echo "\#define PCRE2_CODE_UNIT_WIDTH 8\\n\#include <pcre2.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpcre.o - 2>/dev/null && $(CC) -o testpcre testpcre.o $(LDFLAGS) -lpcre2-8 2>/dev/null && rm testpcre testpcre.o && echo true||echo false) PCRE_CHECK ?= $(shell echo "\#define PCRE2_CODE_UNIT_WIDTH 8\\n\#include <pcre2.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpcre.o - 2>/dev/null && $(CC) -o testpcre testpcre.o $(LDFLAGS) -lpcre2-8 2>/dev/null && rm testpcre testpcre.o && echo true||echo false)
ifeq ($(PCRE_CHECK), true) ifeq ($(PCRE_CHECK), true)
PLUGINS += PCREPlugin CFLAGS += -DWITH_PCRE
PCRE_OBJS = pcre$(OBJSUFFICS)
PCRE_LIBS = $(STATIC_PREFIX) -lpcre2-8 $(STATIC_SUFFIX)
endif endif
PAM_CHECK = $(shell echo "\#include <security/pam_appl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpam.o - 2>/dev/null && $(CC) $(LDFLAGS) -o testpam testpam.o -lpam 2>/dev/null && rm testpam testpam.o && echo true||echo false) PAM_CHECK ?= $(shell echo "\#include <security/pam_appl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpam.o - 2>/dev/null && $(CC) $(LDFLAGS) -o testpam testpam.o -lpam 2>/dev/null && rm testpam testpam.o && echo true||echo false)
ifeq ($(PAM_CHECK), true) ifeq ($(PAM_CHECK), true)
PLUGINS += PamAuth PLUGINS += PamAuth
endif endif
@ -49,14 +71,25 @@ include Makefile.inc
install: all install: all
if [ ! -d "/usr/local/3proxy/bin" ]; then mkdir -p /usr/local/3proxy/bin/; fi if [ ! -d "/usr/local/3proxy/bin" ]; then mkdir -p /usr/local/3proxy/bin/; fi
install bin/3proxy /usr/local/3proxy/bin/3proxy install bin/3proxy /usr/local/3proxy/bin/3proxy
install bin/3proxy_crypt /usr/local/3proxy/bin/3proxy_crypt install bin/$(CRYPT_PREFIX)crypt /usr/local/3proxy/bin/$(CRYPT_PREFIX)crypt
for f in proxy socks pop3p smtpp ftppr tcppm udppm tlspr; do \
if [ -f bin/$(PREFIX)$$f ]; then install bin/$(PREFIX)$$f /usr/local/3proxy/bin/$(PREFIX)$$f; fi; \
done
install scripts/rc.d/3proxy /usr/local/etc/rc.d/3proxy install scripts/rc.d/3proxy /usr/local/etc/rc.d/3proxy
install scripts/add3proxyuser.sh /usr/local/3proxy/bin/ install scripts/add3proxyuser.sh /usr/local/3proxy/bin/
if [ -s /usr/local/etc/3proxy/3proxy.cfg ]; then /usr/local/3proxy/3proxy.cfg already exists ; else install scripts/3proxy.cfg /usr/local/etc/3proxy/; fi if [ -s /usr/local/etc/3proxy/3proxy.cfg ]; then echo /usr/local/3proxy/3proxy.cfg already exists; else install scripts/3proxy.cfg /usr/local/etc/3proxy/; fi
if [ ! -d /var/log/3proxy/ ]; then mkdir /var/log/3proxy/; fi if [ ! -d /var/log/3proxy/ ]; then mkdir /var/log/3proxy/; fi
touch /usr/local/3proxy/passwd touch /usr/local/3proxy/passwd
touch /usr/local/3proxy/counters touch /usr/local/3proxy/counters
touch /usr/local/3proxy/bandlimiters touch /usr/local/3proxy/bandlimiters
install -d $(MANDIR)/man8
install -m 644 man/3proxy.8 $(MANDIR)/man8/3proxy.8
for f in proxy socks pop3p smtpp ftppr tcppm udppm tlspr; do \
if [ -f man/$$f.8 ]; then install -m 644 man/$$f.8 $(MANDIR)/man8/$(PREFIX)$$f.8; fi; \
done
install -m 644 man/3proxy_crypt.8 $(MANDIR)/man8
install -d $(MANDIR)/man5
install -m 644 man/3proxy.cfg.5 $(MANDIR)/man5/3proxy.cfg.5
echo Run /usr/local/3proxy/bin/add3proxyuser.sh to add \'admin\' user echo Run /usr/local/3proxy/bin/add3proxyuser.sh to add \'admin\' user
allplugins: allplugins:

View File

@ -1,17 +1,21 @@
# #
# 3 proxy Makefile for GCC/Linux/Cygwin # 3 proxy Makefile for GCC/Linux/Cygwin
# #
# remove -DNOODBC from CFLAGS and add -lodbc to LIBS to compile with ODBC # add -DWITH_ODBC to CFLAGS and -lodbc to LIBS to compile with ODBC
# library support. Add -DSAFESQL for poorely written ODBC library / drivers. # library support. Add -DSAFESQL for poorely written ODBC library / drivers.
BUILDDIR = ../bin/ BUILDDIR = ../bin/
PREFIX ?= 3proxy_
CRYPT_PREFIX ?= $(PREFIX)
CC ?= gcc CC ?= gcc
CFLAGS := -g -fPIC -O2 -fno-strict-aliasing -c -pthread -DWITHSPLICE -D_GNU_SOURCE -DGETHOSTBYNAME_R -D_THREAD_SAFE -D_REENTRANT -DNOODBC -DFD_SETSIZE=4096 -DWITH_POLL -DWITH_NETFILTER -D WITH_UN $(CFLAGS) CFLAGS ?= -O3 -flto -fPIC
CFLAGS += -fno-strict-aliasing -c -pthread -DWITHSPLICE -D_GNU_SOURCE -DGETHOSTBYNAME_R -D_THREAD_SAFE -D_REENTRANT -DFD_SETSIZE=4096 -DWITH_POLL -DWITH_NETFILTER -D WITH_UN
COUT = -o COUT = -o
LN ?= ${CC} LN ?= ${CC}
DCFLAGS ?= DCFLAGS ?=
LDFLAGS := -fPIC -O2 -fno-strict-aliasing -pthread $(LDFLAGS) LDFLAGS ?= -O3 -flto -fPIC
LDFLAGS += -fno-strict-aliasing -pthread
DLFLAGS ?= -shared DLFLAGS ?= -shared
DLSUFFICS = .ld.so DLSUFFICS = .ld.so
# -lpthreads may be reuqired on some platforms instead of -pthreads # -lpthreads may be reuqired on some platforms instead of -pthreads
@ -30,19 +34,38 @@ MAKEFILE = Makefile.Linux
# PamAuth requires libpam, you may require pam-devel package to be installed # PamAuth requires libpam, you may require pam-devel package to be installed
# SSLPlugin requires -lcrypto -lssl # SSLPlugin requires -lcrypto -lssl
#LIBS = -lcrypto -lssl -ldl #LIBS = -lcrypto -lssl -ldl
LIBS ?= -ldl
#PLUGINS = SSLPlugin StringsPlugin TrafficPlugin PCREPlugin TransparentPlugin PamAuth #PLUGINS = SSLPlugin StringsPlugin TrafficPlugin PCREPlugin TransparentPlugin PamAuth
PLUGINS ?= StringsPlugin TrafficPlugin TransparentPlugin FilePlugin PLUGINS ?= StringsPlugin TrafficPlugin TransparentPlugin FilePlugin
OPENSSL_CHECK = $(shell echo "\#include <openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestssl testssl.o -lcrypto -lssl 2>/dev/null && rm testssl testssl.o && echo true||echo false) ifeq ($(STATIC), true)
LDFLAGS += -static
CFLAGS += -DNOPLUGINS -DNOSTDRESOLVE -DNOCRYPT
ZLIB = -lz -lzstd
PLUGINS =
PAM_CHECK = false
else
LIBS += -ldl
endif
ifeq ($(LIBSTATIC), true)
STATIC_PREFIX = -Wl,-Bstatic
STATIC_SUFFIX = -Wl,-Bdynamic
ZLIB = -lz -lzstd
endif
OPENSSL_CHECK ?= $(shell echo "\#include <openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestssl testssl.o $(STATIC_PREFIX) $(ZLIB) -lcrypto -lssl $(STATIC_SUFFIX) 2>/dev/null && rm testssl testssl.o && echo true||echo false)
ifeq ($(OPENSSL_CHECK), true) ifeq ($(OPENSSL_CHECK), true)
LIBS += -l crypto -l ssl LIBS += $(STATIC_PREFIX) $(ZLIB) -lcrypto -lssl $(STATIC_SUFFIX)
PLUGINS += SSLPlugin CFLAGS += -DWITH_SSL
SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS)
else
ZLIB :=
endif endif
PCRE_CHECK = $(shell echo "\#define PCRE2_CODE_UNIT_WIDTH 8\\n\#include <pcre2.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpcre.o - 2>/dev/null && $(CC) -o testpcre testpcre.o $(LDFLAGS) -lpcre2-8 2>/dev/null && rm testpcre testpcre.o && echo true||echo false) PCRE_CHECK ?= $(shell echo "\#define PCRE2_CODE_UNIT_WIDTH 8\\n\#include <pcre2.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpcre.o - 2>/dev/null && $(CC) -o testpcre testpcre.o $(LDFLAGS) $(STATIC_PREFIX) -lpcre2-8 $(STATIC_SUFFIX) 2>/dev/null && rm testpcre testpcre.o && echo true||echo false)
ifeq ($(PCRE_CHECK), true) ifeq ($(PCRE_CHECK), true)
PLUGINS += PCREPlugin CFLAGS += -DWITH_PCRE
PCRE_OBJS = pcre$(OBJSUFFICS)
PCRE_LIBS = $(STATIC_PREFIX) -lpcre2-8 $(STATIC_SUFFIX)
endif endif
PAM_CHECK = $(shell echo "\#include <security/pam_appl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpam.o - 2>/dev/null && $(CC) $(LDFLAGS) -o testpam testpam.o -lpam 2>/dev/null && rm testpam testpam.o && echo true||echo false) PAM_CHECK ?= $(shell echo "\#include <security/pam_appl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpam.o - 2>/dev/null && $(CC) $(LDFLAGS) -o testpam testpam.o -lpam 2>/dev/null && rm testpam testpam.o && echo true||echo false)
ifeq ($(PAM_CHECK), true) ifeq ($(PAM_CHECK), true)
PLUGINS += PamAuth PLUGINS += PamAuth
endif endif
@ -61,14 +84,15 @@ INSTALL = /usr/bin/install
INSTALL_BIN = $(INSTALL) -m 755 INSTALL_BIN = $(INSTALL) -m 755
INSTALL_DATA = $(INSTALL) -m 644 INSTALL_DATA = $(INSTALL) -m 644
INSTALL_OBJS = bin/3proxy \ INSTALL_OBJS = bin/3proxy \
bin/ftppr \ bin/$(CRYPT_PREFIX)crypt \
bin/3proxy_crypt \ bin/$(PREFIX)ftppr \
bin/pop3p \ bin/$(PREFIX)pop3p \
bin/proxy \ bin/$(PREFIX)proxy \
bin/socks \ bin/$(PREFIX)smtpp \
bin/tcppm \ bin/$(PREFIX)socks \
bin/udppm \ bin/$(PREFIX)tcppm \
bin/tlspr bin/$(PREFIX)tlspr \
bin/$(PREFIX)udppm
INSTALL_CFG = scripts/3proxy.cfg.chroot INSTALL_CFG = scripts/3proxy.cfg.chroot
@ -82,7 +106,7 @@ INSTALL_SYSTEMD_SCRIPT = scripts/3proxy.service
CHROOTDIR = $(DESTDIR)$(chroot_prefix)/3proxy CHROOTDIR = $(DESTDIR)$(chroot_prefix)/3proxy
CHROOTREL = ../..$(chroot_prefix)/3proxy CHROOTREL = ../..$(chroot_prefix)/3proxy
MANDIR3 = $(DESTDIR)$(man_prefix)/man/man3 MANDIR5 = $(DESTDIR)$(man_prefix)/man/man5
MANDIR8 = $(DESTDIR)$(man_prefix)/man/man8 MANDIR8 = $(DESTDIR)$(man_prefix)/man/man8
BINDIR = $(DESTDIR)$(exec_prefix)/bin BINDIR = $(DESTDIR)$(exec_prefix)/bin
ETCDIR = $(DESTDIR)/etc/3proxy ETCDIR = $(DESTDIR)/etc/3proxy
@ -125,10 +149,14 @@ install-etc: install-etc-dir install-etc-default-config
done; done;
install-man: install-man:
$(INSTALL_BIN) -d $(MANDIR3) $(INSTALL_BIN) -d $(MANDIR5)
$(INSTALL_BIN) -d $(MANDIR8) $(INSTALL_BIN) -d $(MANDIR8)
$(INSTALL_DATA) man/*.3 $(MANDIR3) $(INSTALL_DATA) man/3proxy.cfg.5 $(MANDIR5)
$(INSTALL_DATA) man/*.8 $(MANDIR8) $(INSTALL_DATA) man/3proxy.8 $(MANDIR8)
for f in proxy socks pop3p 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)
install-init: install-init:
$(INSTALL_BIN) -d $(INITDDIR) $(INSTALL_BIN) -d $(INITDDIR)

View File

@ -2,12 +2,12 @@
# 3 proxy Makefile for Solaris/SunCC # 3 proxy Makefile for Solaris/SunCC
# #
# #
# remove -DNOODBC from CFLAGS and add -lodbc to LDFLAGS to compile with ODBC # add -DWITH_ODBC to CFLAGS and -lodbc to LDFLAGS to compile with ODBC
# library support. Add -DSAFESQL for poorely written ODBC library / drivers. # library support. Add -DSAFESQL for poorely written ODBC library / drivers.
BUILDDIR = ../bin/ BUILDDIR = ../bin/
CC = cc CC ?= cc
CFLAGS = -xO3 -c -D_SOLARIS -D_THREAD_SAFE -DGETHOSTBYNAME_R -D_REENTRANT -DNOODBC -DFD_SETSIZE=4096 -DWITH_POLL CFLAGS = -xO3 -c -D_SOLARIS -D_THREAD_SAFE -DGETHOSTBYNAME_R -D_REENTRANT -DFD_SETSIZE=4096 -DWITH_POLL
COUT = -o ./ COUT = -o ./
LN = $(CC) LN = $(CC)
LDFLAGS = -xO3 LDFLAGS = -xO3
@ -27,7 +27,20 @@ AFTERCLEAN = (find . -type f -name "*.o" -delete && find src/ -type f -name "Mak
TYPECOMMAND = cat TYPECOMMAND = cat
COMPATLIBS = COMPATLIBS =
MAKEFILE = Makefile.Solaris MAKEFILE = Makefile.Solaris
PLUGINS = StringsPlugin TrafficPlugin PLUGINS = StringsPlugin TrafficPlugin TransparentPlugin FilePlugin
OPENSSL_CHECK = $(shell echo "\#include <openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -o testssl testssl.o -lcrypto -lssl 2>/dev/null && rm testssl testssl.o && echo true||echo false)
ifeq ($(OPENSSL_CHECK), true)
LIBS += -l crypto -l ssl
CFLAGS += -DWITH_SSL
SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS)
endif
PCRE_CHECK = $(shell echo "\#define PCRE2_CODE_UNIT_WIDTH 8\\n\#include <pcre2.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpcre.o - 2>/dev/null && $(CC) -o testpcre testpcre.o $(LDFLAGS) -Wl,-Bstatic -lpcre2-8 -Wl,-Bdynamic 2>/dev/null && rm testpcre testpcre.o && echo true||echo false)
ifeq ($(PCRE_CHECK), true)
CFLAGS += -DWITH_PCRE
PCRE_OBJS = pcre$(OBJSUFFICS)
PCRE_LIBS = -Wl,-Bstatic -lpcre2-8 -Wl,-Bdynamic
endif
include Makefile.inc include Makefile.inc

View File

@ -1,36 +0,0 @@
#
# 3 proxy Makefile for Solaris/gcc
#
#
# remove -DNOODBC from CFLAGS and add -lodbc to LDFLAGS to compile with ODBC
# library support. Add -DSAFESQL for poorely written ODBC library / drivers.
BUILDDIR = ../bin/
CC = gcc
CFLAGS = -O2 -fno-strict-aliasing -c -D_SOLARIS -D_THREAD_SAFE -DGETHOSTBYNAME_R -D_REENTRANT -DNOODBC -DFD_SETSIZE=4096 -DWITH_POLL
COUT = -o ./
LN = $(CC)
LDFLAGS = -O3
DCFLAGS = -fPIC
DLFLAGS = -shared
DLSUFFICS = .ld.so
LIBS = -lpthread -lsocket -lnsl -lresolv -ldl
LIBSPREFIX = -l
LIBSSUFFIX =
LNOUT = -o ./
EXESUFFICS =
OBJSUFFICS = .o
DEFINEOPTION = -D
COMPFILES = *~
REMOVECOMMAND = rm -f
AFTERCLEAN = (find . -type f -name "*.o" -delete && find src/ -type f -name "Makefile.var" -delete && find bin/ -type f -executable -delete) || true
TYPECOMMAND = cat
COMPATLIBS =
MAKEFILE = Makefile.Solaris-gcc
PLUGINS = StringsPlugin TrafficPlugin
include Makefile.inc
allplugins:
@list='$(PLUGINS)'; for p in $$list; do cp Makefile Makefile.var plugins/$$p; cd plugins/$$p ; make ; cd ../.. ; done

View File

@ -1,2 +0,0 @@
SUBDIRS = src man
EXTRA_DIST = doc cfg

View File

@ -1,24 +0,0 @@
#
# 3 proxy Makefile for Microsoft Visual C compiler (for both make and nmake)
#
BUILDDIR = ../bin/
CC = cl
CFLAGS = /FD /MDd /nologo /W3 /ZI /Wp64 /GS /Gs /RTCsu /EHs- /GA /GF /DEBUG /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_WIN32" /c
COUT = /Fo
LN = link
LDFLAGS = /nologo /subsystem:console /machine:I386 /DEBUG
LIBS = ws2_32.lib advapi32.lib odbc32.lib user32.lib
LNOUT = /out:
EXESUFFICS = .exe
OBJSUFFICS = .obj
DEFINEOPTION = /D
COMPFILES = *.pch *.idb
REMOVECOMMAND = del 2>NUL >NUL
TYPECOMMAND = type
COMPATLIBS =
MAKEFILE = Makefile.debug
include Makefile.inc
allplugins:

View File

@ -2,19 +2,20 @@
# 3 proxy Makefile for Microsoft Visual C compiler (for both make and nmake) # 3 proxy Makefile for Microsoft Visual C compiler (for both make and nmake)
# #
# #
# ODBC support is enabled by default on Windows (/D WITH_ODBC, odbc32.lib)
# Add /DSAFESQL to CFLAGS if you are using poorely written/tested ODBC driver # Add /DSAFESQL to CFLAGS if you are using poorely written/tested ODBC driver
BUILDDIR = ../bin/ BUILDDIR = ../bin/
CC = cl CC = cl
VERSION = $(VERSION) VERSION = $(VERSION)
BUILDDATE = $(BUILDDATE) BUILDDATE = $(BUILDDATE)
CFLAGS = /nologo /MT /W3 /Ox /GS /EHs- /GA /GF /D "MSVC" /D "WITH_WSAPOLL" /D "NDEBUG" /D "WIN32" /D "WITH_SSL" /D "_CONSOLE" /D "_MBCS" /D "_WIN32" /Fp"proxy.pch" /FD /c $(BUILDDATE) $(VERSION) CFLAGS = /nologo /MT /W3 /Ox /GS /EHs- /GA /GF /D "MSVC" /D "WITH_WSAPOLL" /D "NDEBUG" /D "WIN32" /D "WITH_SSL" /D "WITH_PCRE" /D "WITH_ODBC" /D "_CONSOLE" /D "_MBCS" /D "_WIN32" /Fp"proxy.pch" /FD /c $(BUILDDATE) $(VERSION)
COUT = /Fo COUT = /Fo
LN = link LN = link
LDFLAGS = /nologo /subsystem:console /incremental:no LDFLAGS = /nologo /subsystem:console /incremental:no
DLFLAGS = /DLL DLFLAGS = /DLL
DLSUFFICS = .dll DLSUFFICS = .dll
LIBS = ws2_32.lib advapi32.lib odbc32.lib user32.lib kernel32.lib Gdi32.lib Crypt32.lib libcrypto.lib libssl.lib LIBS = ws2_32.lib advapi32.lib odbc32.lib user32.lib kernel32.lib Gdi32.lib Crypt32.lib libcrypto.lib libssl.lib pcre2-8.lib
LIBSPREFIX = LIBSPREFIX =
LIBSSUFFIX = .lib LIBSSUFFIX = .lib
LIBEXT = .lib LIBEXT = .lib
@ -27,7 +28,9 @@ REMOVECOMMAND = del
TYPECOMMAND = type TYPECOMMAND = type
COMPATLIBS = COMPATLIBS =
MAKEFILE = Makefile.msvc MAKEFILE = Makefile.msvc
PLUGINS = utf8tocp1251 WindowsAuthentication TrafficPlugin StringsPlugin FilePlugin SSLPlugin PCREPlugin PLUGINS = utf8tocp1251 WindowsAuthentication TrafficPlugin StringsPlugin FilePlugin
SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS)
PCRE_OBJS = pcre$(OBJSUFFICS)
VERFILE = 3proxy.res $(VERFILE) VERFILE = 3proxy.res $(VERFILE)
VERSIONDEP = 3proxy.res $(VERSIONDEP) VERSIONDEP = 3proxy.res $(VERSIONDEP)
AFTERCLEAN = if exist src\*.res (del src\*.res) && if exist src\*.err (del src\*.err) AFTERCLEAN = if exist src\*.res (del src\*.res) && if exist src\*.err (del src\*.err)

View File

@ -1,112 +0,0 @@
#
# 3 proxy Makefile for GCC/Linux/Cygwin
#
#
# remove -DNOODBC from CFLAGS and add -lodbc to LIBS to compile with ODBC
# library support. Add -DSAFESQL for poorely written ODBC library / drivers.
BUILDDIR = ../bin/
CC = mips-openwrt-linux-gcc
CFLAGS ?= -g -O2 -fno-strict-aliasing -c -pthread -DGETHOSTBYNAME_R -D_THREAD_SAFE -D_REENTRANT -DNOODBC -DFD_SETSIZE=4096 -DWITH_POLL -DWITH_NETFILTER
COUT = -o
LN = $(CC)
DCFLAGS = -fPIC
LDFLAGS ?= -O2 -fno-strict-aliasing -pthread -s
DLFLAGS = -shared
DLSUFFICS = .ld.so
# -lpthreads may be reuqired on some platforms instead of -pthreads
LIBSPREFIX = -l
LIBSSUFFIX =
LNOUT = -o
EXESUFFICS =
OBJSUFFICS = .o
DEFINEOPTION = -D
COMPFILES = *~
REMOVECOMMAND = rm -f
AFTERCLEAN = (find . -type f -name "*.o" -delete && find src/ -type f -name "Makefile.var" -delete && find bin/ -type f -executable -delete) || true
TYPECOMMAND = cat
COMPATLIBS =
MAKEFILE = Makefile.openwrt-mips
# PamAuth requires libpam, you may require pam-devel package to be installed
# SSLPlugin requires -lcrypto -lssl
#LIBS = -lcrypto -lssl -ldl
LIBS ?= -ldl
#PLUGINS = SSLPlugin StringsPlugin TrafficPlugin PCREPlugin TransparentPlugin PamAuth
PLUGINS ?= StringsPlugin TrafficPlugin TransparentPlugin
OPENSSL_CHECK = $(shell echo "\#include <openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | cc -x c $(CFLAGS) $(LDFLAGS) -l crypto -l ssl -o testssl - 2>/dev/null && rm testssl && echo true||echo false)
ifeq ($(OPENSSL_CHECK), true)
LIBS += -l crypto -l ssl
PLUGINS += SSLPlugin
endif
PCRE_CHECK = $(shell echo "\#define PCRE2_CODE_UNIT_WIDTH 8\\n\#include <pcre2.h>\\n int main(){return 0;}" | tr -d \\\\ | cc -x c $(CFLAGS) $(LDFLAGS) -l pcre2-8 -o testpcre - 2>/dev/null && rm testpcre && echo true||echo false)
ifeq ($(PCRE_CHECK), true)
PLUGINS += PCREPlugin
endif
PAM_CHECK = $(shell echo "\#include <security/pam_appl.h>\\n int main(){return 0;}" | tr -d \\\\ | cc -x c $(CFLAGS) $(LDFLAGS) -l pam -o testpam - 2>/dev/null && rm testpam && echo true||echo false)
ifeq ($(PAM_CHECK), true)
PLUGINS += PamAuth
endif
include Makefile.inc
allplugins:
@list='$(PLUGINS)'; for p in $$list; do cp Makefile Makefile.var plugins/$$p; cd plugins/$$p ; make ; cd ../.. ; done
DESTDIR =
prefix = /usr/local
exec_prefix = $(prefix)
man_prefix = $(prefix)/share
INSTALL = /usr/bin/install
INSTALL_BIN = $(INSTALL) -m 755
INSTALL_DATA = $(INSTALL) -m 644
INSTALL_OBJS = src/3proxy \
src/ftppr \
src/3proxy_crypt \
src/pop3p \
src/proxy \
src/socks \
src/tcppm \
src/udppm
INSTALL_CFG_OBJS = scripts/3proxy.cfg \
scripts/add3proxyuser.sh
INSTALL_CFG_DEST = config
INSTALL_CFG_OBJS2 = passwd counters bandlimiters
MANDIR3 = $(DESTDIR)$(man_prefix)/man/man3
MANDIR8 = $(DESTDIR)$(man_prefix)/man/man8
BINDIR = $(DESTDIR)$(exec_prefix)/bin
ETCDIR = $(DESTDIR)$(prefix)/etc/3proxy
install-bin:
$(INSTALL_BIN) -d $(BINDIR)
$(INSTALL_BIN) -s $(INSTALL_OBJS) $(BINDIR)
install-etc-dir:
$(INSTALL_BIN) -d $(ETCDIR)
install-etc-default-config:
if [ -f $(ETCDIR)/$(INSTALL_CFG_DEST) ]; then \
: ; \
else \
$(INSTALL_DATA) $(INSTALL_CFG_OBJS) $(ETCDIR)/$(INSTALL_CFG_DEST) \
fi
install-etc: install-etc-dir
for file in $(INSTALL_CFG_OBJS2); \
do \
touch $(ETCDIR)/$$file; chmod 0600 $(ETCDIR)/$$file; \
done;
install-man:
$(INSTALL_BIN) -d $(MANDIR3)
$(INSTALL_BIN) -d $(MANDIR8)
$(INSTALL_DATA) man/*.3 $(MANDIR3)
$(INSTALL_DATA) man/*.8 $(MANDIR8)
install: install-bin install-etc install-man

View File

@ -2,17 +2,22 @@
# 3 proxy Makefile for GCC/Unix # 3 proxy Makefile for GCC/Unix
# #
# #
# remove -DNOODBC from CFLAGS and add -lodbc to LDFLAGS to compile with ODBC # add -DWITH_ODBC to CFLAGS and -lodbc to LDFLAGS to compile with ODBC
# library support. Add -DSAFESQL for poorely written ODBC library / drivers. # library support. Add -DSAFESQL for poorely written ODBC library / drivers.
BUILDDIR = ../bin/ BUILDDIR = ../bin/
PREFIX ?= 3proxy_
CRYPT_PREFIX ?= $(PREFIX)
MANDIR ?= /usr/share/man
CC ?= gcc CC ?= gcc
# you may need -L/usr/pkg/lib for older NetBSD versions # you may need -L/usr/pkg/lib for older NetBSD versions
CFLAGS := -g -O2 -fno-strict-aliasing -c -pthread -D_THREAD_SAFE -D_REENTRANT -DNOODBC -DFD_SETSIZE=4096 -DWITH_POLL -DWITH_UN $(CFLAGS) CFLAGS ?= -O3 -flto
CFLAGS += -fno-strict-aliasing -c -pthread -D_THREAD_SAFE -D_REENTRANT -DFD_SETSIZE=4096 -DWITH_POLL -DWITH_UN
COUT = -o COUT = -o
LN ?= $(CC) LN ?= $(CC)
LDFLAGS ?= -O2 -fno-strict-aliasing -pthread LDFLAGS ?= -O3 -flto
LDFLAGS += -pthread -fno-strict-aliasing
# -lpthreads may be reuqired on some platforms instead of -pthreads # -lpthreads may be reuqired on some platforms instead of -pthreads
# -ldl or -lld may be required for some platforms # -ldl or -lld may be required for some platforms
DCFLAGS ?= -fPIC DCFLAGS ?= -fPIC
@ -32,16 +37,33 @@ TYPECOMMAND = cat
COMPATLIBS = COMPATLIBS =
MAKEFILE = Makefile.unix MAKEFILE = Makefile.unix
PLUGINS ?= StringsPlugin TrafficPlugin TransparentPlugin FilePlugin PLUGINS ?= StringsPlugin TrafficPlugin TransparentPlugin FilePlugin
OPENSSL_CHECK = $(shell echo "\#include <openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestssl testssl.o -lcrypto -lssl 2>/dev/null && rm testssl testssl.o && echo true||echo false) ifeq ($(STATIC), true)
LDFLAGS += -static
CFLAGS += -DNOPLUGINS -DNOSTDRESOLVE -DNOCRYPT
ZLIB = -lz -lzstd
PLUGINS =
PAM_CHECK = false
endif
ifeq ($(LIBSTATIC), true)
STATIC_PREFIX = -Wl,-Bstatic
STATIC_SUFFIX = -Wl,-Bdynamic
ZLIB = -lz -lzstd
endif
OPENSSL_CHECK ?= $(shell echo "\#include <openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestssl testssl.o $(STATIC_PREFIX) $(ZLIB) -lcrypto -lssl $(STATIC_SUFFIX) 2>/dev/null && rm testssl testssl.o && echo true||echo false)
ifeq ($(OPENSSL_CHECK), true) ifeq ($(OPENSSL_CHECK), true)
LIBS += -l crypto -l ssl LIBS += $(STATIC_PREFIX) $(ZLIB) -lcrypto -lssl $(STATIC_SUFFIX)
PLUGINS += SSLPlugin CFLAGS += -DWITH_SSL
SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS)
else
ZLIB :=
endif endif
PCRE_CHECK = $(shell echo "\#define PCRE2_CODE_UNIT_WIDTH 8\\n\#include <pcre2.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpcre.o - 2>/dev/null && $(CC) -o testpcre testpcre.o $(LDFLAGS) -lpcre2-8 2>/dev/null && rm testpcre testpcre.o && echo true||echo false) PCRE_CHECK ?= $(shell echo "\#define PCRE2_CODE_UNIT_WIDTH 8\\n\#include <pcre2.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpcre.o - 2>/dev/null && $(CC) -o testpcre testpcre.o $(LDFLAGS) $(STATIC_PREFIX) -lpcre2-8 $(STATIC_SUFFIX) 2>/dev/null && rm testpcre testpcre.o && echo true||echo false)
ifeq ($(PCRE_CHECK), true) ifeq ($(PCRE_CHECK), true)
PLUGINS += PCREPlugin CFLAGS += -DWITH_PCRE
PCRE_OBJS = pcre$(OBJSUFFICS)
PCRE_LIBS = $(STATIC_PREFIX) -lpcre2-8 $(STATIC_SUFFIX)
endif endif
PAM_CHECK = $(shell echo "\#include <security/pam_appl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpam.o - 2>/dev/null && $(CC) $(LDFLAGS) -o testpam testpam.o -lpam 2>/dev/null && rm testpam testpam.o && echo true||echo false) PAM_CHECK ?= $(shell echo "\#include <security/pam_appl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpam.o - 2>/dev/null && $(CC) $(LDFLAGS) -o testpam testpam.o -lpam 2>/dev/null && rm testpam testpam.o && echo true||echo false)
ifeq ($(PAM_CHECK), true) ifeq ($(PAM_CHECK), true)
PLUGINS += PamAuth PLUGINS += PamAuth
endif endif
@ -49,17 +71,28 @@ endif
include Makefile.inc include Makefile.inc
install: all install: all
if [ ! -d "/usr/local/3proxy/bin" ]; then mkdir -p /usr/local/3proxy/bin/; fi if [ ! -d "/usr/local/3proxy/bin" ]; then mkdir -p /usr/local/3proxy/bin/; fi
install bin/3proxy /usr/local/3proxy/bin/3proxy install bin/3proxy /usr/local/3proxy/bin/3proxy
install bin/3proxy_crypt /usr/local/3proxy/bin/3proxy_crypt install bin/$(CRYPT_PREFIX)crypt /usr/local/3proxy/bin/$(CRYPT_PREFIX)crypt
install scripts/rc.d/3proxy /usr/local/etc/rc.d/3proxy for f in proxy socks pop3p smtpp ftppr tcppm udppm tlspr; do \
install scripts/add3proxyuser.sh /usr/local/3proxy/bin/ if [ -f bin/$(PREFIX)$$f ]; then install bin/$(PREFIX)$$f /usr/local/3proxy/bin/$(PREFIX)$$f; fi; \
if [ -s /usr/local/etc/3proxy/3proxy.cfg ]; then /usr/local/3proxy/3proxy.cfg already exists ; else install scripts/3proxy.cfg /usr/local/etc/3proxy/; fi done
if [ ! -d /var/log/3proxy/ ]; then mkdir /var/log/3proxy/; fi install scripts/rc.d/3proxy /usr/local/etc/rc.d/3proxy
touch /usr/local/3proxy/passwd install scripts/add3proxyuser.sh /usr/local/3proxy/bin/
touch /usr/local/3proxy/counters if [ -s /usr/local/etc/3proxy/3proxy.cfg ]; then echo /usr/local/3proxy/3proxy.cfg already exists; else install scripts/3proxy.cfg /usr/local/etc/3proxy/; fi
touch /usr/local/3proxy/bandlimiters if [ ! -d /var/log/3proxy/ ]; then mkdir /var/log/3proxy/; fi
echo Run /usr/local/3proxy/bin/add3proxyuser.sh to add \'admin\' user touch /usr/local/3proxy/passwd
touch /usr/local/3proxy/counters
touch /usr/local/3proxy/bandlimiters
install -d $(MANDIR)/man8
install -m 644 man/3proxy.8 $(MANDIR)/man8/3proxy.8
for f in proxy socks pop3p smtpp ftppr tcppm udppm tlspr; do \
if [ -f man/$$f.8 ]; then install -m 644 man/$$f.8 $(MANDIR)/man8/$(PREFIX)$$f.8; fi; \
done
install -m 644 man/3proxy_crypt.8 $(MANDIR)/man8
install -d $(MANDIR)/man5
install -m 644 man/3proxy.cfg.5 $(MANDIR)/man5/3proxy.cfg.5
echo Run /usr/local/3proxy/bin/add3proxyuser.sh to add \'admin\' user
allplugins: allplugins:
@list='$(PLUGINS)'; for p in $$list; do cp Makefile Makefile.var plugins/$$p; cd plugins/$$p ; make ; cd ../.. ; done @list='$(PLUGINS)'; for p in $$list; do cp Makefile Makefile.var plugins/$$p; cd plugins/$$p ; make ; cd ../.. ; done

View File

@ -6,14 +6,13 @@
BUILDDIR = ../bin/ BUILDDIR = ../bin/
CC = cl CC = cl
CFLAGS = /nologo /Ox /MT /D "NOIPV6" /D "NODEBUG" /D "NOODBC" /D "NORADIUS" /D"WATCOM" /D "MSVC" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_WIN32" /D "PRId64=\"I64d\"" /D "PRIu64=\"I64u\"" /D "SCNu64=\"I64u\"" /D "SCNx64=\"I64x\"" /D "SCNd64=\"I64d\"" /D "PRIx64=\"I64x\"" /c $(VERSION) $(BUILDDATE) CFLAGS = /nologo /Ox /MT /D "NOIPV6" /D "NODEBUG" /D "NORADIUS" /D"WATCOM" /D "MSVC" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_WIN32" /D "PRId64=\"I64d\"" /D "PRIu64=\"I64u\"" /D "SCNu64=\"I64u\"" /D "SCNx64=\"I64x\"" /D "SCNd64=\"I64d\"" /D "PRIx64=\"I64x\"" /c $(VERSION) $(BUILDDATE)
COUT = /Fo COUT = /Fo
LN = link LN = link
LDFLAGS = /nologo /subsystem:console /incremental:no LDFLAGS = /nologo /subsystem:console /incremental:no
DLFLAGS = /DLL DLFLAGS = /DLL
DLSUFFICS = .dll DLSUFFICS = .dll
LIBS = ws2_32.lib advapi32.lib user32.lib kernel32.lib LIBS = ws2_32.lib advapi32.lib user32.lib kernel32.lib
LIBSOLD = libeay32MT.lib ssleay32MT.lib
LIBSPREFIX = LIBSPREFIX =
LIBSSUFFIX = .lib LIBSSUFFIX = .lib
LIBEXT = .lib LIBEXT = .lib

View File

@ -2,19 +2,20 @@
# 3 proxy Makefile for GCC/windows # 3 proxy Makefile for GCC/windows
# #
# #
# remove -DNOODBC from CFLAGS and add -lodbc to LDFLAGS to compile with ODBC # ODBC support is enabled by default on Windows (-DWITH_ODBC, -lodbc32)
# library support
BUILDDIR = ../bin/ BUILDDIR = ../bin/
CC ?= gcc CC ?= gcc
CFLAGS := -O2 -s -c -mthreads -DWITH_WSAPOLL $(CFLAGS) CFLAGS ?= -O3 -flto
CFLAGS += -fno-strict-aliasing -c -mthreads -DWITH_WSAPOLL -DWITH_ODBC
COUT = -o COUT = -o
LN ?= $(CC) LN ?= $(CC)
LDFLAGS := -O2 -s -mthreads $(LDFLAGS) LDFLAGS ?= -O3 -flto
LDFLAGS += -fno-strict-aliasing -mthreads
DLFLAGS ?= -shared DLFLAGS ?= -shared
DLSUFFICS = .dll DLSUFFICS = .dll
LIBS := -lws2_32 -lodbc32 -ladvapi32 -luser32 $(LIBS) LIBS += -lws2_32 -lodbc32 -ladvapi32 -luser32 -lbcrypt
LIBSPREFIX = -l LIBSPREFIX = -l
LIBSSUFFIX = LIBSSUFFIX =
LNOUT = -o LNOUT = -o
@ -37,7 +38,8 @@ ifndef OPENSSL_CHECK
OPENSSL_CHECK = $(shell echo "\#include <openssl/ssl.h>\\n int main(){return 0;}" | tr -d '\\\\' | cc -x c $(CFLAGS) $(LDFLAGS) -l crypto -l ssl -o testssl - 2>/dev/null && rm testssl && echo true||echo false) OPENSSL_CHECK = $(shell echo "\#include <openssl/ssl.h>\\n int main(){return 0;}" | tr -d '\\\\' | cc -x c $(CFLAGS) $(LDFLAGS) -l crypto -l ssl -o testssl - 2>/dev/null && rm testssl && echo true||echo false)
ifeq ($(OPENSSL_CHECK), true) ifeq ($(OPENSSL_CHECK), true)
LIBS += -l crypto -l ssl LIBS += -l crypto -l ssl
PLUGINS += SSLPlugin CFLAGS += -DWITH_SSL
SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS)
endif endif
PAM_CHECK = $(shell echo "\#include <security/pam_appl.h>\\n int main(){return 0;}" | tr -d '\\\\' | cc -x c $(CFLAGS) $(LDFLAGS) -l pam -o testpam - 2>/dev/null && rm testpam && echo true||echo false) PAM_CHECK = $(shell echo "\#include <security/pam_appl.h>\\n int main(){return 0;}" | tr -d '\\\\' | cc -x c $(CFLAGS) $(LDFLAGS) -l pam -o testpam - 2>/dev/null && rm testpam && echo true||echo false)
ifeq ($(PAM_CHECK), true) ifeq ($(PAM_CHECK), true)
@ -45,7 +47,9 @@ ifeq ($(PAM_CHECK), true)
endif endif
PCRE_CHECK = $(shell echo "\#define PCRE2_CODE_UNIT_WIDTH 8\\n#include <pcre2.h>\\n int main(){return 0;}" | tr -d '\\\\' | cc -x c $(CFLAGS) $(LDFLAGS) -lpcre2-8 -o testpcre - 2>/dev/null && rm testpcre && echo true||echo false) PCRE_CHECK = $(shell echo "\#define PCRE2_CODE_UNIT_WIDTH 8\\n#include <pcre2.h>\\n int main(){return 0;}" | tr -d '\\\\' | cc -x c $(CFLAGS) $(LDFLAGS) -lpcre2-8 -o testpcre - 2>/dev/null && rm testpcre && echo true||echo false)
ifeq ($(PCRE_CHECK), true) ifeq ($(PCRE_CHECK), true)
PLUGINS += PCREPlugin CFLAGS += -DWITH_PCRE
PCRE_OBJS = pcre$(OBJSUFFICS)
PCRE_LIBS = -lpcre2-8
endif endif
endif endif

View File

@ -1,6 +1,6 @@
# 3APA3A 3proxy tiny proxy server # 3APA3A 3proxy tiny proxy server
(c) 2002-2025 by Vladimir '3APA3A' Dubrovin <3APA3A@security.nnov.ru> (c) 2002-2026 by Vladimir '3APA3A' Dubrovin <vlad@3proxy.org>
## Branches ## Branches

View File

@ -1,10 +1,11 @@
man/3proxy.8 man/3proxy.8
man/3proxy.cfg.3 man/3proxy.cfg.5
man/ftppr.8 man/3proxy_ftppr.8
man/pop3p.8 man/3proxy_pop3p.8
man/tlspr.8 man/3proxy_tlspr.8
man/proxy.8 man/3proxy_proxy.8
man/smtpp.8 man/3proxy_smtpp.8
man/socks.8 man/3proxy_socks.8
man/tcppm.8 man/3proxy_tcppm.8
man/udppm.8 man/3proxy_udppm.8
man/3proxy_crypt.8

15
debian/copyright vendored
View File

@ -4,17 +4,10 @@ Upstream-Contact: 3proxy@3proxy.org
Source: https://3proxy.org/ Source: https://3proxy.org/
Files: * Files: *
Copyright: 2000-2020 3APA3A, Vladimir Dubrovin, 3proxy.org Copyright: 2000-2026 Vladimir Dubrovin <vlad@3proxy.org>
License: BSD-3-clause or Apache or GPL-2+ or LGPL-2+ License: BSD-3-clause or Apache or GPL-2+ or LGPL-2+
Files: src/libs/md*.* Files: src/libs/blake2*.*
Copyright: 1990,1991,1992 RSA Data Security, Inc Copyright: 2012, Samuel Neves <sneves@dei.uc.pt>
License: public-domain License: public-domain (CC0 1.0 Universal) or OpenSSL license or Apache 2.0
Files: src/libs/regex.*
Copyright: Henry Spencer
License: public-domain
Files: src/libs/smbdes.c
Copyright: Andrew Tridgell 1998
License: GPL-2+

26
doc/changelog/0/7/0 Normal file
View File

@ -0,0 +1,26 @@
3proxy 0.7
This release is partially forced: while no new significant functions are
added, 0.7 is code is much more stable and less buggy than 0.6. Since
there is no new development for a long time, except few minor bugfixes,
I decided to finally release 0.7. You may want it if you:
Use HTTP proxy
Use 3proxy under *BSD/Mac OS X/iPhone OS
Use plugins, specially traffic related ones, like PCRE.
I have no time for active developement. There are interesting features
in nearly ready state, e.g. SSL support / SSL decryption via
certificates spoofing, NAT support and SSL auto-detection. You can step
into development, if you are interested.
There are some configuration changes:
auth iponly is now default (because most misconfigurations were
because of default auth none)
maxconn is now 500 by default (because WebKit browsers ignore
standards and create a lot of connections even if proxy is configured)
NTLM is disabled by default (-n options, -n1 to enable) because
NTLMv1 is disabled by default in Windows since Vista and there is no
NTLMv2 library with compatible license. Report me, if any.

35
doc/changelog/0/7/1 Normal file
View File

@ -0,0 +1,35 @@
3proxy-0.7.1.4
!! Fix transparent flag not reset after keep-alive connection, can lead to
3proxy-0.7.1.3
! traffic displayed incorrectly
! archiver doesn't add suffix if logname contains macro
! fix potential race condition on configuration reload
! fix FTP over HTTP authentication
3proxy-0.7.1.2
! Request / header size limitation relaxed for HTTP proxy
3proxy 0.7.1.1
! Linux compilation issues resolved
3proxy 0.7.1
Minor improvements and bugfixes:
+ Windows icons added
+ Warnings added for most common misconfigurations
+ ftppr NLSD command supported
! Ignore NTLM handshake if NTLM is not enabled
!! memcpy replaced with memmove for overlapped region
! better EINTR handling on *nix
! FTP proxy debugging output removed (introduced in 0.7), binding for data connection corrected
! memory leak fixed in ldapauth plugin

9
doc/changelog/0/8/0 Normal file
View File

@ -0,0 +1,9 @@
+ IPv6 support
+ back connect support
+ name resolution over TCP, parent proxy support for dnspr
+ SSLPlugin for TLS/SSL traffic decryption
! multiple race conditions fixed
! reduced memory usage
! Generate Forwarded: header instead of X-Forwarded-For:
! Default name resolution is non-blocking in *nix
! multiple race conditions fixed on configuration reload

1
doc/changelog/0/8/1 Normal file
View File

@ -0,0 +1 @@
!!Fix: destination IP may be not checked against ACL

2
doc/changelog/0/8/10 Normal file
View File

@ -0,0 +1,2 @@
! Fix: parent proxy can be used in some cases where it shouldn't
! Fix: bandlimiters may not work for older connections on configuration reload

9
doc/changelog/0/8/11 Normal file
View File

@ -0,0 +1,9 @@
Minor bugfixes / improvements:
! Fixed: deadlock on insufficient resources
! Fixed: race condition in ssl_plugin
! Fixed: minor memory leak on configuration reload
! Fixed: recursion detection was not working
! Fixed: %n for IPv6 in logging terminates log record
! Fixed: reverse PTR validation (required for dnsauth)
! Fixed: error on external 0.0.0.0 for NOIPV6 (light version)
+ Better support for IPv6 in ftppr

5
doc/changelog/0/8/12 Normal file
View File

@ -0,0 +1,5 @@
Bugfixes:
! Fixed hostname support in SOCKSv5 UDP portmapping
! -fno-strict-aliasing added to gcc options (compiling without this option can lead to unpredictable issues under Debian with gcc 6 and potentially others)
! Fixed LDAP plugin compilation issues (LDAP plugin is still listed as unsupported though)
and some minor fixes and improvements.

3
doc/changelog/0/8/13 Normal file
View File

@ -0,0 +1,3 @@
Bugfixes:
!! Fixed out-of-bound write and few minor bugs on configuration saving in admin
! fixed: $ is not correctly handled in the beginning of quoted line on configuration parsing

3
doc/changelog/0/8/2 Normal file
View File

@ -0,0 +1,3 @@
!! Fix transparent flag not reset after keep-alive connection, can lead to DoS by authenticated user.
! Do not use SO_REUSEADDR by default (leads to random 00013 errors under some glibc versions)
! Use SASIZE() instead of sizeof() in bind() for FreeBSD compatibility

1
doc/changelog/0/8/3 Normal file
View File

@ -0,0 +1 @@
! fixed: use SASIZE() instead of sizeof() in connect() for FreeBSD compatibility

5
doc/changelog/0/8/4 Normal file
View File

@ -0,0 +1,5 @@
+ Build PamPlugin on *nix
+ stacksize and -S options, stacksize defaults changed for FreeBSD
+ extip redirection type added
! SSL plugin fix to correct handling of certificates path
! fixed random errors on IPv6 connect

1
doc/changelog/0/8/5 Normal file
View File

@ -0,0 +1 @@
!Fix: mutex was used prior to initialization on 'log' command processing

1
doc/changelog/0/8/6 Normal file
View File

@ -0,0 +1 @@
! Fix: random 00012 errors in some configurations

15
doc/changelog/0/8/7 Normal file
View File

@ -0,0 +1,15 @@
! Fix 'daemon' command for Linux
! Fix 'extip' redirections 00009 errors
! Fix counters for older Win platforms
! Resolve logging race conditions
! attempt to fix pam_auth race conditions
! FTP proxy workaround for broken gethostname() on some libc limplementations
! authcache IP matching corrected
! fix SOCKSv5 BIND/UDP ASSOC
! use setreuid/setregid instead of setuid / setgid
+ OpenWatcom makefiles for Windows
+ -u2 support for proxy
+ support %i in logformat
+ force/noforce configuration commands to disconnect / do not disconnect clients if nolonger match ACL after configuration change
+ support longer external passwords

3
doc/changelog/0/8/8 Normal file
View File

@ -0,0 +1,3 @@
!! Fix resolver for non-compressed reply parsing (on mixed-case sensitive resolvers)
! Fix plugins export on OpenWatcom compiler (light version)
! Fix SOCKSv5

1
doc/changelog/0/8/9 Normal file
View File

@ -0,0 +1 @@
! Fix: tcppm may fail if used with parent proxy

6
doc/changelog/0/9/0 Normal file
View File

@ -0,0 +1,6 @@
+ Socket options, interface binding
+ Connection limiting / connection rate limiting
+ RADIUS support (beta)
+ Zero copy (splice) support for Linux
+ Possibility to limit user to single IP (via authentication cache)
! bugfixes, improvements

8
doc/changelog/0/9/1 Normal file
View File

@ -0,0 +1,8 @@
Bugfixes:
! Fixed: socket may be closed before all data received/sent
! Fixed: bandlimin non-working
! Fixed: countall/nocountall
! Fixed: few race conditions
Improvements:
+ deb/rpm build, systemd support (experimental)

9
doc/changelog/0/9/2 Normal file
View File

@ -0,0 +1,9 @@
Bugfixes:
! Fixed: bandwidth limiters (once again)
! Fixed: data filtering plugins (PCREPlugin, SSLPlugin). SSLPlugin use on Linux requires to disable splice (-s0)
! FIxed: standalone proxies do not react on HUP (Ctrl+C) in Linux/Unix
! Fixed: few minor bugs
Improvements:
+ deb for arm platforms (experimental)
+ Openssl 1.1 support for SSLPlugin

11
doc/changelog/0/9/3 Normal file
View File

@ -0,0 +1,11 @@
Bugfixes:
! Fixed: systemd description file (proxy may fail to start after reboot or via systemctl)
! Fixed: group/account creation in installation scripts
! Fixed: countall/nocounall do not work in some configurations
! Fixed: counters do not work if counter file is not specified
! Fixed: counters without rotation (type N) are incorrectly shown in web admin interface
! Fixed: %n may be incomplete or missed in long log records
! Fixed: connect back functionality does not work
Improvements:
+ Docker builds

4
doc/changelog/0/9/4 Normal file
View File

@ -0,0 +1,4 @@
! Fix: invalid handling of '-' character in ACL hostname
! Fix: minor bugfixes and improvements
+ parentretry command added (defaults to 2) to retry connections to parent proxies
- icqpr related code (OSCAR proxy) removed, due to drop of OSCAR support by messengers

7
doc/changelog/0/9/5 Normal file
View File

@ -0,0 +1,7 @@
!! Security fix: proxy can potentially crash on on some platforms due to overlapping regions in strcpy() (thanks to @lenix123 for reporting)
+ new proxy service type: `tlspr` - SNI proxy, may also be used as parent `tls` type, sniffs hostname from TLS handhake, read more in https://github.com/3proxy/3proxy/wiki/tlspr https://github.com/3proxy/3proxy/wiki/How-To-(incomplete)#TLSPR
+ new proxy service type: `auto` - autodetect proxy type between `proxy` and `socks`
+ SSLPlugin is rewritten, production-ready, supports TLS (SSL) server (may be used to create https:// type proxy), certificates checks and cypher options, see https://github.com/3proxy/3proxy/wiki/SSLPlugin
+ -g option is added for grace delay to reduce CPU load, see https://github.com/3proxy/3proxy/wiki/High-Load
! Multiple minor bugfixes
! More supported sockets options

9
doc/changelog/0/9/6 Normal file
View File

@ -0,0 +1,9 @@
+ ssl_client and multiple configuration options added to SSLPlugin, SSLPlugin code significantly improved and bugfixed. See https://github.com/3proxy/3proxy/wiki/SSLPlugin. 3proxy can now be used as stunnel replacement for many scenarios.
+ HAProxy proxy protocol v1 support as client and server, add -H option for service to expect HA proxy v1 protocol header, use ha parent type: parent 1000 ha 0.0.0.0 0 to send v1 header.
+ tlspr is supported in auto
+ tlspr supports -s option, it breaks HELLO packet to prevent some DPIs from detecting SNI
+ maxseg configuration option and TCP_MAXSEG socket flag support added. It sets maximum size of TCP segment to fix PathMTU discovery problems
+ -Ne / -Ni options added to specify external / internal NAT address for SOCKSv5
+ cmake environment added
! External pcre2 (pcre2-8) library is used for PCRE, pcre code is removed from 3proxy
! Multiple minor bugfixes

View File

@ -1,508 +0,0 @@
{\rtf1\adeflang1025\ansi\ansicpg1251\uc1\adeff0\deff0\stshfdbch0\stshfloch0\stshfhich0\stshfbi0\deflang1049\deflangfe1049{\fonttbl{\f0\froman\fcharset204\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f2\fmodern\fcharset204\fprq1{\*\panose 02070309020205020404}Courier New;}
{\f3\froman\fcharset2\fprq2{\*\panose 05050102010706020507}Symbol;}{\f10\fnil\fcharset2\fprq2{\*\panose 05000000000000000000}Wingdings;}{\f39\froman\fcharset0\fprq2 Times New Roman;}{\f37\froman\fcharset238\fprq2 Times New Roman CE;}
{\f40\froman\fcharset161\fprq2 Times New Roman Greek;}{\f41\froman\fcharset162\fprq2 Times New Roman Tur;}{\f42\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f43\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
{\f44\froman\fcharset186\fprq2 Times New Roman Baltic;}{\f45\froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f59\fmodern\fcharset0\fprq1 Courier New;}{\f57\fmodern\fcharset238\fprq1 Courier New CE;}
{\f60\fmodern\fcharset161\fprq1 Courier New Greek;}{\f61\fmodern\fcharset162\fprq1 Courier New Tur;}{\f62\fbidi \fmodern\fcharset177\fprq1 Courier New (Hebrew);}{\f63\fbidi \fmodern\fcharset178\fprq1 Courier New (Arabic);}
{\f64\fmodern\fcharset186\fprq1 Courier New Baltic;}{\f65\fmodern\fcharset163\fprq1 Courier New (Vietnamese);}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;
\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\stylesheet{
\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0 \fs24\lang1049\langfe1049\cgrid\langnp1049\langfenp1049 \snext0 Normal;}{\*\cs10 \additive \ssemihidden
Default Paragraph Font;}{\*\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tscellwidthfts0\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv
\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \fs20\lang1024\langfe1024\cgrid\langnp1024\langfenp1024 \snext11 \ssemihidden Normal Table;}}
{\*\latentstyles\lsdstimax156\lsdlockeddef0}{\*\listtable{\list\listtemplateid-1938272566{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'01\'00;}{\levelnumbers\'01;}\rtlch\fcs1 \af0
\ltrch\fcs0 \fbias0 \fi-360\li360\jclisttab\tx360\lin360 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'03\'00.\'01;}{\levelnumbers\'01\'03;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fbias0
\fi-360\li360\jclisttab\tx360\lin360 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'05\'00.\'01.\'02;}{\levelnumbers\'01\'03\'05;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fbias0 \fi-720\li720
\jclisttab\tx720\lin720 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'07\'00.\'01.\'02.\'03;}{\levelnumbers\'01\'03\'05\'07;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fbias0 \fi-720\li720
\jclisttab\tx720\lin720 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'09\'00.\'01.\'02.\'03.\'04;}{\levelnumbers\'01\'03\'05\'07\'09;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fbias0
\fi-1080\li1080\jclisttab\tx1080\lin1080 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'0b\'00.\'01.\'02.\'03.\'04.\'05;}{\levelnumbers\'01\'03\'05\'07\'09\'0b;}\rtlch\fcs1 \af0
\ltrch\fcs0 \fbias0 \fi-1080\li1080\jclisttab\tx1080\lin1080 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'0d\'00.\'01.\'02.\'03.\'04.\'05.\'06;}{\levelnumbers
\'01\'03\'05\'07\'09\'0b\'0d;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fbias0 \fi-1440\li1440\jclisttab\tx1440\lin1440 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext
\'0f\'00.\'01.\'02.\'03.\'04.\'05.\'06.\'07;}{\levelnumbers\'01\'03\'05\'07\'09\'0b\'0d\'0f;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fbias0 \fi-1440\li1440\jclisttab\tx1440\lin1440 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1
\levelspace0\levelindent0{\leveltext\'11\'00.\'01.\'02.\'03.\'04.\'05.\'06.\'07.\'08;}{\levelnumbers\'01\'03\'05\'07\'09\'0b\'0d\'0f\'11;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fbias0 \fi-1800\li1800\jclisttab\tx1800\lin1800 }{\listname ;}\listid233053280}
{\list\listtemplateid269381388\listhybrid{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\leveltemplateid1994686728\'02\'00.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fbias0
\fi-360\li720\jclisttab\tx720\lin720 }{\listlevel\levelnfc255\levelnfcn255\leveljc0\leveljcn0\levelfollow0\levelstartat0\levelspace0\levelindent0{\leveltext\leveltemplateid-2036938464\'00;}{\levelnumbers;}\rtlch\fcs1 \af0 \ltrch\fcs0 \jclisttab\tx360 }
{\listlevel\levelnfc255\levelnfcn255\leveljc0\leveljcn0\levelfollow0\levelstartat0\levelspace0\levelindent0{\leveltext\leveltemplateid1578941516\'00;}{\levelnumbers;}\rtlch\fcs1 \af0 \ltrch\fcs0 \jclisttab\tx360 }{\listlevel\levelnfc255\levelnfcn255
\leveljc0\leveljcn0\levelfollow0\levelstartat0\levelspace0\levelindent0{\leveltext\leveltemplateid936021434\'00;}{\levelnumbers;}\rtlch\fcs1 \af0 \ltrch\fcs0 \jclisttab\tx360 }{\listlevel\levelnfc255\levelnfcn255\leveljc0\leveljcn0\levelfollow0
\levelstartat0\levelspace0\levelindent0{\leveltext\leveltemplateid-1323636224\'00;}{\levelnumbers;}\rtlch\fcs1 \af0 \ltrch\fcs0 \jclisttab\tx360 }{\listlevel\levelnfc255\levelnfcn255\leveljc0\leveljcn0\levelfollow0\levelstartat0\levelspace0\levelindent0
{\leveltext\leveltemplateid-1892018578\'00;}{\levelnumbers;}\rtlch\fcs1 \af0 \ltrch\fcs0 \jclisttab\tx360 }{\listlevel\levelnfc255\levelnfcn255\leveljc0\leveljcn0\levelfollow0\levelstartat0\levelspace0\levelindent0{\leveltext\leveltemplateid-108487922
\'00;}{\levelnumbers;}\rtlch\fcs1 \af0 \ltrch\fcs0 \jclisttab\tx360 }{\listlevel\levelnfc255\levelnfcn255\leveljc0\leveljcn0\levelfollow0\levelstartat0\levelspace0\levelindent0{\leveltext\leveltemplateid-4969626\'00;}{\levelnumbers;}\rtlch\fcs1 \af0
\ltrch\fcs0 \jclisttab\tx360 }{\listlevel\levelnfc255\levelnfcn255\leveljc0\leveljcn0\levelfollow0\levelstartat0\levelspace0\levelindent0{\leveltext\leveltemplateid1135759886\'00;}{\levelnumbers;}\rtlch\fcs1 \af0 \ltrch\fcs0 \jclisttab\tx360 }{\listname
;}\listid243993609}{\list\listtemplateid1411046654{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat2\levelspace0\levelindent0{\leveltext\'01\'00;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fbias0 \fi-360\li360
\jclisttab\tx360\lin360 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat2\levelspace0\levelindent0{\leveltext\'03\'00.\'01;}{\levelnumbers\'01\'03;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fbias0 \fi-360\li720\jclisttab\tx720\lin720 }
{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'05\'00.\'01.\'02;}{\levelnumbers\'01\'03\'05;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fbias0 \fi-720\li1440\jclisttab\tx1440\lin1440 }{\listlevel
\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'07\'00.\'01.\'02.\'03;}{\levelnumbers\'01\'03\'05\'07;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fbias0 \fi-720\li1800\jclisttab\tx1800\lin1800 }{\listlevel
\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'09\'00.\'01.\'02.\'03.\'04;}{\levelnumbers\'01\'03\'05\'07\'09;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fbias0 \fi-1080\li2520\jclisttab\tx2520\lin2520 }
{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'0b\'00.\'01.\'02.\'03.\'04.\'05;}{\levelnumbers\'01\'03\'05\'07\'09\'0b;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fbias0 \fi-1080\li2880
\jclisttab\tx2880\lin2880 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'0d\'00.\'01.\'02.\'03.\'04.\'05.\'06;}{\levelnumbers\'01\'03\'05\'07\'09\'0b\'0d;}\rtlch\fcs1 \af0 \ltrch\fcs0
\fbias0 \fi-1440\li3600\jclisttab\tx3600\lin3600 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'0f\'00.\'01.\'02.\'03.\'04.\'05.\'06.\'07;}{\levelnumbers
\'01\'03\'05\'07\'09\'0b\'0d\'0f;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fbias0 \fi-1440\li3960\jclisttab\tx3960\lin3960 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext
\'11\'00.\'01.\'02.\'03.\'04.\'05.\'06.\'07.\'08;}{\levelnumbers\'01\'03\'05\'07\'09\'0b\'0d\'0f\'11;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fbias0 \fi-1800\li4680\jclisttab\tx4680\lin4680 }{\listname ;}\listid368384829}{\list\listtemplateid1424627480\listhybrid
{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\leveltemplateid1868871046\'01-;}{\levelnumbers;}\loch\af0\hich\af0\dbch\af0\fbias0 \fi-360\li420\jclisttab\tx420\lin420 }{\listlevel
\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid68747267\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li1140\jclisttab\tx1140\lin1140 }{\listlevel\levelnfc23\levelnfcn23
\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid68747269\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li1860\jclisttab\tx1860\lin1860 }{\listlevel\levelnfc23\levelnfcn23\leveljc0
\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid68747265\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li2580\jclisttab\tx2580\lin2580 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0
\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid68747267\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li3300\jclisttab\tx3300\lin3300 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1
\lvltentative\levelspace0\levelindent0{\leveltext\leveltemplateid68747269\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li4020\jclisttab\tx4020\lin4020 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative
\levelspace0\levelindent0{\leveltext\leveltemplateid68747265\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li4740\jclisttab\tx4740\lin4740 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0
\levelindent0{\leveltext\leveltemplateid68747267\'01o;}{\levelnumbers;}\f2\fbias0 \fi-360\li5460\jclisttab\tx5460\lin5460 }{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\lvltentative\levelspace0\levelindent0{\leveltext
\leveltemplateid68747269\'01\u-3929 ?;}{\levelnumbers;}\f10\fbias0 \fi-360\li6180\jclisttab\tx6180\lin6180 }{\listname ;}\listid634527506}{\list\listtemplateid1914202178\listhybrid{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0
\levelstartat1\levelspace0\levelindent0{\leveltext\leveltemplateid745160830\'02\'00.;}{\levelnumbers\'01;}\rtlch\fcs1 \af0 \ltrch\fcs0 \fbias0 \fi-360\li720\jclisttab\tx720\lin720 }{\listlevel\levelnfc255\levelnfcn255\leveljc0\leveljcn0\levelfollow0
\levelstartat0\levelspace0\levelindent0{\leveltext\leveltemplateid-1816475770\'00;}{\levelnumbers;}\rtlch\fcs1 \af0 \ltrch\fcs0 \jclisttab\tx360 }{\listlevel\levelnfc255\levelnfcn255\leveljc0\leveljcn0\levelfollow0\levelstartat0\levelspace0\levelindent0
{\leveltext\leveltemplateid-715330988\'00;}{\levelnumbers;}\rtlch\fcs1 \af0 \ltrch\fcs0 \jclisttab\tx360 }{\listlevel\levelnfc255\levelnfcn255\leveljc0\leveljcn0\levelfollow0\levelstartat0\levelspace0\levelindent0{\leveltext\leveltemplateid1569232270
\'00;}{\levelnumbers;}\rtlch\fcs1 \af0 \ltrch\fcs0 \jclisttab\tx360 }{\listlevel\levelnfc255\levelnfcn255\leveljc0\leveljcn0\levelfollow0\levelstartat0\levelspace0\levelindent0{\leveltext\leveltemplateid-297370836\'00;}{\levelnumbers;}\rtlch\fcs1 \af0
\ltrch\fcs0 \jclisttab\tx360 }{\listlevel\levelnfc255\levelnfcn255\leveljc0\leveljcn0\levelfollow0\levelstartat0\levelspace0\levelindent0{\leveltext\leveltemplateid-346936770\'00;}{\levelnumbers;}\rtlch\fcs1 \af0 \ltrch\fcs0 \jclisttab\tx360 }{\listlevel
\levelnfc255\levelnfcn255\leveljc0\leveljcn0\levelfollow0\levelstartat0\levelspace0\levelindent0{\leveltext\leveltemplateid416698944\'00;}{\levelnumbers;}\rtlch\fcs1 \af0 \ltrch\fcs0 \jclisttab\tx360 }{\listlevel\levelnfc255\levelnfcn255\leveljc0
\leveljcn0\levelfollow0\levelstartat0\levelspace0\levelindent0{\leveltext\leveltemplateid-596467262\'00;}{\levelnumbers;}\rtlch\fcs1 \af0 \ltrch\fcs0 \jclisttab\tx360 }{\listlevel\levelnfc255\levelnfcn255\leveljc0\leveljcn0\levelfollow0\levelstartat0
\levelspace0\levelindent0{\leveltext\leveltemplateid11278156\'00;}{\levelnumbers;}\rtlch\fcs1 \af0 \ltrch\fcs0 \jclisttab\tx360 }{\listname ;}\listid1261259807}}{\*\listoverridetable{\listoverride\listid1261259807\listoverridecount0\ls1}
{\listoverride\listid634527506\listoverridecount0\ls2}{\listoverride\listid233053280\listoverridecount0\ls3}{\listoverride\listid243993609\listoverridecount0\ls4}{\listoverride\listid368384829\listoverridecount0\ls5}}{\*\rsidtbl \rsid1339617\rsid1586505
\rsid1600374\rsid1771507\rsid1986875\rsid2235853\rsid2296829\rsid2567226\rsid2701137\rsid3560132\rsid3671104\rsid3692728\rsid4980816\rsid5776876\rsid5975359\rsid6257560\rsid6570302\rsid7013593\rsid7235628\rsid7749673\rsid8087560\rsid8326885\rsid8672163
\rsid8675175\rsid9981679\rsid10440144\rsid10497064\rsid10908886\rsid12060716\rsid12261729\rsid12544729\rsid12806430\rsid13111076\rsid13909505\rsid15236432\rsid15609114\rsid15928529\rsid16077654}{\*\generator Microsoft Word 11.0.0000;}{\info
{\title 3proxy developer reference}{\author Vladimir Dubrovin}{\operator Vladimir Dubrovin}{\creatim\yr2007\mo11\dy23\hr19\min28}{\revtim\yr2008\mo1\dy22\hr19\min28}{\version8}{\edmins86}{\nofpages8}{\nofwords2396}{\nofchars13662}{\*\company Sandy}
{\nofcharsws16026}{\vern24611}{\*\password 00000000}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}{\xmlns2 urn:schemas-microsoft-com:office:smarttags}}
\paperw11906\paperh16838\margl1701\margr850\margt1134\margb1134\gutter0\ltrsect
\deftab708\widowctrl\ftnbj\aenddoc\donotembedsysfont1\donotembedlingdata0\grfdocevents0\validatexml1\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors1\noxlattoyen\expshrtn\noultrlspc\dntblnsbdb\nospaceforul\formshade\horzdoc\dgmargin
\dghspace180\dgvspace180\dghorigin1701\dgvorigin1134\dghshow1\dgvshow1
\jexpand\viewkind1\viewscale130\viewzk2\pgbrdrhead\pgbrdrfoot\splytwnine\ftnlytwnine\htmautsp\nolnhtadjtbl\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\viewnobound1\snaptogridincell
\allowfieldendsel\wrppunct\asianbrkrule\rsidroot10497064\newtblstyruls\nogrowautofit \fet0{\*\wgrffmtfilter 013f}\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\headery708\footery708\colsx708\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\*\pnseclvl1
\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5
\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang
{\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs24\alang1025 \ltrch\fcs0
\fs24\lang1049\langfe1049\cgrid\langnp1049\langfenp1049 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid13111076
\par }\pard \ltrpar\qc \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid2235853 {\rtlch\fcs1 \af0\afs32 \ltrch\fcs0 \fs32\lang1033\langfe1049\langnp1033\insrsid10497064\charrsid12261729 3proxy developer reference}{
\rtlch\fcs1 \af0\afs32 \ltrch\fcs0 \fs32\lang1033\langfe1049\langnp1033\insrsid10497064
\par }{\rtlch\fcs1 \af0\afs20 \ltrch\fcs0 \fs20\lang1033\langfe1049\langnp1033\insrsid2235853\charrsid12261729 $Id: devref.rtf,v 1.4 2008/01/24 08:44:57 vlad Exp $
\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid10497064
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \b\lang1033\langfe1049\langnp1033\insrsid10497064\charrsid12060716 \hich\af0\dbch\af0\loch\f0 1.\tab}}\pard \ltrpar\ql \fi-360\li720\ri0\widctlpar
\jclisttab\tx720\wrapdefault\aspalpha\aspnum\faauto\ls4\adjustright\rin0\lin720\itap0\pararsid6570302 {\rtlch\fcs1 \af0 \ltrch\fcs0 \b\lang1033\langfe1049\langnp1033\insrsid10497064\charrsid12060716 Understanding Internal 3proxy structure
\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid10497064 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid10497064
\par 3proxy is implemented as multithread application. Server model is implemented as \'93one connection \endash one thread\'94. It means, for every client connection new thre
ad is created. This model is effective enough under Windows, because it allows it avoid thread creation on asynchronous operations, yet under most POSIX systems this model can not be considered as most efficient. It\rquote
s planned for (very far in future) release to implement more efficient model, where single thread can serve few clients.
\par
\par
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid10497064 \hich\af0\dbch\af0\loch\f0 1.1\tab}}\pard \ltrpar\ql \fi-360\li360\ri0\widctlpar
\jclisttab\tx360\wrapdefault\aspalpha\aspnum\faauto\ls3\ilvl1\adjustright\rin0\lin360\itap0\pararsid6570302 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid10497064 main thread:
\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid6570302 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid6570302
\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid10497064 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid10497064
3proxy begins with main thread. This thread parses configuration}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid4980816 file and starts main loop}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid10497064 . }{
\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid8672163 During configuration file parsing }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid8672163\charrsid8672163 struct extaparam conf;}{\rtlch\fcs1 \af0
\ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid8672163 structure is filled and service threads are started.
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid3560132
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid6570302 Main loop cycle }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid2701137 takes approximately 1 second and }{\rtlch\fcs1 \af0 \ltrch\fcs0
\lang1033\langfe1049\langnp1033\insrsid6570302 does these tasks:}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid10497064
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid6570302 \hich\af0\dbch\af0\loch\f0 -\tab}}\pard \ltrpar\ql \fi-360\li420\ri0\widctlpar
\jclisttab\tx420\wrapdefault\aspalpha\aspnum\faauto\ls2\adjustright\rin0\lin420\itap0\pararsid6570302 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid6570302 re-reads configuration}{\rtlch\fcs1 \af0 \ltrch\fcs0
\lang1033\langfe1049\langnp1033\insrsid8672163 file}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid6570302 , if necessary
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid6570302 \hich\af0\dbch\af0\loch\f0 -\tab}performs scheduled tasks
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid6570302 \hich\af0\dbch\af0\loch\f0 -\tab}monitors files (\lquote monitor}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid4980816 \rquote
command}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid6570302 )}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid2701137 , approx. once in a minute}{\rtlch\fcs1 \af0 \ltrch\fcs0
\lang1033\langfe1049\langnp1033\insrsid6570302
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid6570302 \hich\af0\dbch\af0\loch\f0 -\tab}rotates main logfile
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid6570302 \hich\af0\dbch\af0\loch\f0 -\tab}dumps counters to }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid2701137
file, approx. once in a minute}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid6570302
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid2701137 \hich\af0\dbch\af0\loch\f0 -\tab}}\pard \ltrpar\ql \fi-360\li420\ri0\widctlpar
\jclisttab\tx420\wrapdefault\aspalpha\aspnum\faauto\ls2\adjustright\rin0\lin420\itap0\pararsid2701137 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid2701137 performs termination, if required
\par }\pard \ltrpar\ql \li60\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin60\itap0\pararsid8672163 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid3560132
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid2701137 I}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid8672163 t\rquote s guaranteed every configuration and schedule command is executed from the same thread.
\par Main thread is implemented in }{\rtlch\fcs1 \af0 \ltrch\fcs0 \b\lang1033\langfe1049\langnp1033\insrsid8672163\charrsid12544729 3proxy.c}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid8672163
\par }\pard \ltrpar\ql \li60\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin60\itap0\pararsid6570302 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid6570302
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid8672163 \hich\af0\dbch\af0\loch\f0 1.2\tab}}\pard \ltrpar\ql \fi-360\li360\ri0\widctlpar
\jclisttab\tx360\wrapdefault\aspalpha\aspnum\faauto\ls3\ilvl1\adjustright\rin0\lin360\itap0\pararsid8672163 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid8672163 service thread}{\rtlch\fcs1 \af0 \ltrch\fcs0
\lang1033\langfe1049\langnp1033\insrsid6570302
\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid8672163 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid8672163
\par Service threads are started immediately, than service command (e.g. \lquote proxy\rquote or \lquote socks\rquote ) are found during configuration file parsing. Each command creates new thread. Thread does these tasks:
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid8672163 \hich\af0\dbch\af0\loch\f0 -\tab}}\pard \ltrpar\ql \fi-360\li420\ri0\widctlpar
\jclisttab\tx420\wrapdefault\aspalpha\aspnum\faauto\ls2\adjustright\rin0\lin420\itap0\pararsid8672163 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid8672163 parses service command arguments and fills \lquote }{\rtlch\fcs1 \af0
\ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid8672163\charrsid6257560 struct srvparam srv}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid8672163 \rquote structure with service configuration and \lquote }{\rtlch\fcs1 \af0
\ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid8672163\charrsid6257560 struct clientparam defparam}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid8672163 \rquote structure with default client configuration
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid6257560 \hich\af0\dbch\af0\loch\f0 -\tab}}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid6257560 initializes filters}{\rtlch\fcs1 \af0
\ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid3560132 (filter_open)}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid6257560\charrsid8672163
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid6257560 \hich\af0\dbch\af0\loch\f0 -\tab}}\pard \ltrpar\ql \fi-360\li420\ri0\widctlpar
\jclisttab\tx420\wrapdefault\aspalpha\aspnum\faauto\ls2\adjustright\rin0\lin420\itap0\pararsid6257560 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid6257560 creates }{\rtlch\fcs1 \af0 \ltrch\fcs0
\lang1033\langfe1049\langnp1033\insrsid2701137 and initializes }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid6257560 listening service socket
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid2701137 \hich\af0\dbch\af0\loch\f0 -\tab}}\pard \ltrpar\ql \fi-360\li420\ri0\widctlpar
\jclisttab\tx420\wrapdefault\aspalpha\aspnum\faauto\ls2\adjustright\rin0\lin420\itap0\pararsid3560132 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid2701137 enters into service loop}{\rtlch\fcs1 \af0 \ltrch\fcs0
\lang1033\langfe1049\langnp1033\insrsid3560132
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid3560132 \hich\af0\dbch\af0\loch\f0 -\tab}terminates filters (filter_close)
\par }\pard \ltrpar\ql \li60\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin60\itap0\pararsid2701137 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid3560132
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid2701137 service loop:
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid2701137 \hich\af0\dbch\af0\loch\f0 -\tab}}\pard \ltrpar\ql \fi-360\li420\ri0\widctlpar
\jclisttab\tx420\wrapdefault\aspalpha\aspnum\faauto\ls2\adjustright\rin0\lin420\itap0\pararsid2701137 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid2701137
checks for configuration reload (approximately every second), thread exits if configuration reloaded or 3proxy is in terminating state.
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid2701137 \hich\af0\dbch\af0\loch\f0 -\tab}accepts client connection and creates \lquote }{\rtlch\fcs1 \af0 \ltrch\fcs0
\i\lang1033\langfe1049\langnp1033\insrsid2701137 struct clientparam new}{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid2701137\charrsid6257560 param}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid2701137
\rquote structure with client configuration
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid3560132 \hich\af0\dbch\af0\loch\f0 -\tab}}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid3560132
creates/checks client filters (filter_client)
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid3560132 \hich\af0\dbch\af0\loch\f0 -\tab}creates client thread with newly created \lquote }{\rtlch\fcs1 \af0 \ltrch\fcs0
\i\lang1033\langfe1049\langnp1033\insrsid3560132 struct clientparam new}{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid3560132\charrsid6257560 param}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid3560132
\rquote
\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid6570302 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid6570302
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid5975359 service threads are implemented in }{\rtlch\fcs1 \af0 \ltrch\fcs0 \b\lang1033\langfe1049\langnp1033\insrsid7749673\charrsid12544729 proxymain.c}{\rtlch\fcs1 \af0 \ltrch\fcs0
\lang1033\langfe1049\langnp1033\insrsid5975359\charrsid7749673
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid5975359
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid3560132 Please note: struct clientparam is freed and }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid3560132\charrsid3560132 filter_clear}{\rtlch\fcs1 \af0
\ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid3560132 is executed from different (client) thread.
\par
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid3560132 \hich\af0\dbch\af0\loch\f0 1.3\tab}}\pard \ltrpar\ql \fi-360\li360\ri0\widctlpar
\jclisttab\tx360\wrapdefault\aspalpha\aspnum\faauto\ls3\ilvl1\adjustright\rin0\lin360\itap0\pararsid3560132 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid3560132 client thread
\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid7749673 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid7749673
\par Client threads are started from service thread. Client thread:
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid7749673 \hich\af0\dbch\af0\loch\f0 -\tab}}\pard \ltrpar\ql \fi-360\li420\ri0\widctlpar
\jclisttab\tx420\wrapdefault\aspalpha\aspnum\faauto\ls2\adjustright\rin0\lin420\itap0\pararsid7749673 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid7749673
reads client request (except portmappers) with authentication information and request headers (if any).
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid5776876 \hich\af0\dbch\af0\loch\f0 -\tab}}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid5776876 filters request (if any) with }{
\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid5776876\charrsid5776876 filter_request}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid7749673
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid5776876 \hich\af0\dbch\af0\loch\f0 -\tab}}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid5776876 filters headers (if any) with }{
\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid5776876\charrsid5776876 filter_header_cli}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid5776876
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid5776876 \hich\af0\dbch\af0\loch\f0 -\tab}performs authentication and authorization
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid5776876 \hich\af0\dbch\af0\loch\f0 -\tab}established connection with server
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid5776876 \hich\af0\dbch\af0\loch\f0 -\tab}sends request to server
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid5776876 \hich\af0\dbch\af0\loch\f0 -\tab}}\pard \ltrpar\ql \fi-360\li420\ri0\widctlpar
\jclisttab\tx420\wrapdefault\aspalpha\aspnum\faauto\ls2\adjustright\rin0\lin420\itap0\pararsid3560132 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid5776876 filters server headers (if any)}{\rtlch\fcs1 \af0 \ltrch\fcs0
\lang1033\langfe1049\langnp1033\insrsid3560132
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid5776876 \hich\af0\dbch\af0\loch\f0 -\tab}}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid5776876 maps client end s
erver sockets to transmit data between client and server
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid5776876 \hich\af0\dbch\af0\loch\f0 -\tab}}\pard \ltrpar\ql \fi-360\li420\ri0\widctlpar
\jclisttab\tx420\wrapdefault\aspalpha\aspnum\faauto\ls2\adjustright\rin0\lin420\itap0\pararsid5776876 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid5776876 logs request. Global counters are also updated on this operation
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid5776876 \hich\af0\dbch\af0\loch\f0 -\tab}}\pard \ltrpar\ql \fi-360\li420\ri0\widctlpar
\jclisttab\tx420\wrapdefault\aspalpha\aspnum\faauto\ls2\adjustright\rin0\lin420\itap0\pararsid3560132 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid5776876 clears client filters (}{\rtlch\fcs1 \af0 \ltrch\fcs0
\lang1033\langfe1049\langnp1033\insrsid5776876\charrsid5776876 filter_clear}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid5776876 )
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid5776876 \hich\af0\dbch\af0\loch\f0 -\tab}frees }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid5776876\charrsid5776876
struct clientparam}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid5776876 data
\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid5776876 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid5776876
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid10908886 in some point client thread may loop to process few client requests from the same connection (e.g. HTTP \lquote established\rquote connection in \lquote proxy\rquote ).
\par
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid5776876 Socket mapping does:
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid5776876 \hich\af0\dbch\af0\loch\f0 -\tab}}\pard \ltrpar\ql \fi-360\li420\ri0\widctlpar
\jclisttab\tx420\wrapdefault\aspalpha\aspnum\faauto\ls2\adjustright\rin0\lin420\itap0\pararsid5776876 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid5776876 caches data in internal client and server buffers
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid5776876 \hich\af0\dbch\af0\loch\f0 -\tab}delays data transmit to limit bandwidth
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid5776876 \hich\af0\dbch\af0\loch\f0 -\tab}performs data filtering (}{\rtlch\fcs1 \af0 \ltrch\fcs0
\lang1033\langfe1049\langnp1033\insrsid5776876\charrsid5776876 filter_data_cli}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid5776876 / }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid5776876\charrsid5776876
filter_data_srv}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid5776876 )
\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid3560132 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid3560132
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid1586505 client threads are implemented in }{\rtlch\fcs1 \af0 \ltrch\fcs0 \b\lang1033\langfe1049\langnp1033\insrsid1586505\charrsid12544729 proxy.c}{\rtlch\fcs1 \af0 \ltrch\fcs0
\lang1033\langfe1049\langnp1033\insrsid1586505 , }{\rtlch\fcs1 \af0 \ltrch\fcs0 \b\lang1033\langfe1049\langnp1033\insrsid1586505\charrsid12544729 socks.c}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid1586505 , }{\rtlch\fcs1 \af0
\ltrch\fcs0 \b\lang1033\langfe1049\langnp1033\insrsid1586505\charrsid12544729 pop3p.c}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid1586505 etc.
\par
\par {\listtext\pard\plain\ltrpar \rtlch\fcs1 \af0 \ltrch\fcs0 \b\lang1033\langfe1049\langnp1033\insrsid1586505\charrsid12060716 \hich\af0\dbch\af0\loch\f0 2.\tab}}\pard \ltrpar\ql \fi-360\li720\ri0\widctlpar
\jclisttab\tx720\wrapdefault\aspalpha\aspnum\faauto\ls4\adjustright\rin0\lin720\itap0\pararsid1586505 {\rtlch\fcs1 \af0 \ltrch\fcs0 \b\lang1033\langfe1049\langnp1033\insrsid1586505\charrsid12060716 Hacking into 3proxy code with plugins
\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid3560132 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid1586505
\par }\pard \ltrpar\ql \li0\ri0\widctlpar\jclisttab\tx720\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid2296829 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid2296829 2.1 }{\rtlch\fcs1 \af0 \ltrch\fcs0
\lang1033\langfe1049\langnp1033\insrsid1586505 What is 3proxy plugin
\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid1586505 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid1586505
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid10440144 3proxy plugin is any dynamic/shared library. There is no specific requirement for plugin, actually you can load any dynamic library with \lquote plugin\rquote
command. No linking with any libraries are required. However, to interoperate with 3proxy dynamic library must have an export function 3proxy may call to pass the structure with required information.}{\rtlch\fcs1 \af0 \ltrch\fcs0
\lang1033\langfe1049\langnp1033\insrsid1586505
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid15928529
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid10440144\charrsid10440144 typedef int (*PLUGINFUNC) (struct pluginlink *pluginlink, int argc, char** argv);
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid10440144
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid10440144\charrsid10440144 struct pluginlink}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid10440144
is a structure with export information, explained later, argc and argv are argument counter and array of arguments of \'93plugin\'94 command. Plugin should report it\rquote
s status with integer return value. 0 is success, positive value indicates non-recoverable error, 3proxy do not parse rest of configuration and enters into termination state, negative value indicates recoverable value, 3proxy logs warning (if possible).}{
\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid12544729 In case of C++, all 3proxy functions/structures must be extern \'93C\'94.}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid10440144
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid15928529
\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid15928529 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid15928529 All 3proxy structures/functions descriptions are located in
}{\rtlch\fcs1 \af0 \ltrch\fcs0 \b\lang1033\langfe1049\langnp1033\insrsid15928529\charrsid15928529 structures.h}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid15928529
\par }\pard \ltrpar\ql \li360\ri0\widctlpar\jclisttab\tx720\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin360\itap0\pararsid2296829 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid2296829
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid15928529
\par }\pard \ltrpar\ql \li0\ri0\widctlpar\jclisttab\tx720\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid2296829 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid2296829 2.2 }{\rtlch\fcs1 \af0 \ltrch\fcs0
\lang1033\langfe1049\langnp1033\insrsid12544729 Understanding pluginlink structure
\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid12544729 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid12544729
\par Because there is no linking between 3proxy and plugin, all 3proxy functions and structures are passed with pluginlink structure. Pluginlink is actually a collection of pointers to 3proxy internal structures and functions. Because plug
inlink is constantly extending, you should see it\rquote s definitions in }{\rtlch\fcs1 \af0 \ltrch\fcs0 \b\lang1033\langfe1049\langnp1033\insrsid12544729\charrsid12544729 structures.h}{\rtlch\fcs1 \af0 \ltrch\fcs0
\lang1033\langfe1049\langnp1033\insrsid12544729 .
\par
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid13909505 most important}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid12544729 are:
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid13909505
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid12544729\charrsid8087560 struct symbol symbols;
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid8087560 \'93symbols\'94
is a kind of name/value export table, made as a list. It can be used by plugins to exchange information and functions between plugins, e.g. to export functions from one plugin to another, where pluginlink is useless, because it\rquote s static. It
\rquote s quite simple:}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid12544729
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid8087560
\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid8087560 {\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid8087560\charrsid8087560 struct symbol \{
\par \tab struct symbol *next;
\par \tab char * name;
\par \tab void * value;
\par \};
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid8087560
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid13909505 n}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid8087560 ame \endash is a name of function or structure
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid13909505 v}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid8087560 alue \endash is it\rquote s value.
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid13909505
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid8087560 u}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid13909505 se}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid8087560
pluginlink->fundbyname function to lookup, e.g.
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid13909505
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid8087560\charrsid13909505 anotherplugindata = pluginlink->findbyname(\'93anotherplugindata\'94);
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid13909505
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid8087560 To export }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid13909505 something from your plugin, add your structure to this list.}{\rtlch\fcs1 \af0
\ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid8087560\charrsid8087560
\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid12544729 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid8087560\charrsid12544729
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid12544729\charrsid13909505 struct extparam *conf;
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid12544729 pointer to conf structure, it holds all current 3proxy configuration
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid12544729\charrsid12544729
\par }\pard \ltrpar\ql \li360\ri0\widctlpar\jclisttab\tx720\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin360\itap0\pararsid2296829 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid2296829
\par }\pard \ltrpar\ql \li0\ri0\widctlpar\jclisttab\tx720\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid2296829 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid2296829 2.3 }{\rtlch\fcs1 \af0 \ltrch\fcs0
\lang1033\langfe1049\langnp1033\insrsid12544729 How to get control within plugin}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid10440144
\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid12544729 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid12544729
\par There are few points you can get control for your plugin, after it\rquote s loaded with \lquote plugin\rquote command.
\par
\par {\listtext\tab}}\pard \ltrpar\ql \li0\ri0\widctlpar\jclisttab\tx360\wrapdefault\aspalpha\aspnum\faauto\ls4\ilvl2\adjustright\rin0\lin0\itap0\pararsid13909505 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid2296829 2.3.1 }{\rtlch\fcs1
\af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid12544729 Adding configuration command processor with struct command structure
\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid13909505 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid13909505
\par A list of configuration file command, available from 3proxy.cfg is extendable. Each command is defined by }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid13909505\charrsid13909505 struct commands}{\rtlch\fcs1 \af0 \ltrch\fcs0
\lang1033\langfe1049\langnp1033\insrsid13909505 :
\par
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid13909505\charrsid13909505 struct commands \{
\par \tab struct commands *next;
\par \tab char * command;
\par \tab int (* handler)(int argc, unsigned char ** argv);
\par \tab int minargs;
\par \tab int maxargs;\tab
\par \};
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid13909505
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid13909505\charrsid13909505 struct commands *next}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid13909505 - next element in list}{\rtlch\fcs1 \af0 \ltrch\fcs0
\lang1033\langfe1049\langnp1033\insrsid13909505\charrsid13909505
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid13909505\charrsid13909505 char * command}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid13909505 \endash command name
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid13909505\charrsid13909505 int (* handler)(i}{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid13909505 nt argc, unsigned char ** argv)}{\rtlch\fcs1 \af0
\ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid13909505 \endash command handler. It\rquote s called than \lquote command\rquote is found in configuration files, argc is a number of arguments, counting command itself, argv is array of arguments.
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid13909505\charrsid12060716 minargs}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid13909505 \endash minimum number of arguments command support (>= 1)
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid12060716\charrsid12060716 maxargs}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid12060716 \endash
maximum number of arguments command support, 0 means infinity.}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid13909505\charrsid13909505
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid13909505
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid16077654 Handler r}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid3671104
eturn value of 0 indicates command is successfully processed. Positive return value indicates non-recoverable error, 3proxy enter}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid16077654 s}{\rtlch\fcs1 \af0 \ltrch\fcs0
\lang1033\langfe1049\langnp1033\insrsid3671104 }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid16077654 termination state. Negative value indicate
s 3proxy to continue to process command list, it makes it possible to set few handlers for the same command.}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid3671104
\par
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid12060716 A list of the command is pointed by pluginlinks->}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid12060716\charrsid12060716 commandhandlers}{\rtlch\fcs1
\af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid12060716 ; you must insert you command after first one (do not replace pluginlink->}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid12060716\charrsid12060716 commandhandlers}{
\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid12060716 ). It\rquote s guaranteed at least 1 dummy command is always present.}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid12060716\charrsid12060716
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid12060716
\par Example:
\par
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid12060716\charrsid12060716 int mycommandhandler(int argc, unsigned char **argv);
\par struct commands mycommand;
\par
\par mycommand.command = \'93mycommand\'94;
\par mycommand.handler = mycommandhandler;
\par mycommand.intargs = 1;
\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid12060716 {\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid12060716\charrsid12060716 mycommand.intargs = 2;
\par mycommand.next = pluginslinks->commandhandlers->next;
\par pluginslink->commandhandlers->next = &mycommand;
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid12060716
\par Adds processor for \'93mycommand\'94 command with zero on one arguments.}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid12060716\charrsid13909505
\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid13909505 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid13909505
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid12060716 Adding configuration command is useful, if your plugin expects configuration data.
\par
\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid3671104 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid3671104
\par {\listtext\tab}}\pard \ltrpar\ql \li0\ri0\widctlpar\jclisttab\tx360\wrapdefault\aspalpha\aspnum\faauto\ls4\ilvl2\adjustright\rin0\lin0\itap0\pararsid3671104 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid2296829 2.3.2 }{\rtlch\fcs1
\af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid3671104 Adding authentication method with }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid3671104\charrsid3671104 struct auth}{\rtlch\fcs1 \af0 \ltrch\fcs0
\lang1033\langfe1049\langnp1033\insrsid3671104
\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid3671104 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid3671104
\par 3proxy supports authentication and authorization. Authentication process determines user account (for example by user
name and password), authorization checks, if user account has a right to access given resource and optionally establishes a connection, if required.
\par
\par \lquote auth\rquote command combines both authentication and authorization method. It\rquote s extandable with struct auth list:
\par
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid3671104\charrsid16077654 struct auth \{
\par \tab struct auth *next;
\par \tab AUTHFUNC authenticate;
\par \tab AUTHFUNC authorize;
\par \tab char * desc;
\par \};
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid3671104
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid3671104\charrsid16077654 char * desc}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid3671104 \endash name of authentication/authorization method}{\rtlch\fcs1
\af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid3671104\charrsid3671104
\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid13909505 {\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid3671104\charrsid16077654 authenticate}{\rtlch\fcs1 \af0
\ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid3671104 \endash name of authentication function}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid12060716
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid3671104\charrsid16077654 authorize}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid3671104 \endash name of authorization function
\par
\par pluginlink->}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid3671104\charrsid3671104 authfuncs}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid3671104
points to list of authenticataction structures. Like above, new structure must be inserted after fiest one (or to the end of the list).
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid16077654
\par First, authentication is called, if authentication indicates OK status (return value 0), authorization is called. Normally, \lquote }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid16077654\charrsid16077654 checkACL}{\rtlch\fcs1 \af0
\ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid16077654 \rquote (pluginlink->checkACL) is called as authorization function to check user\rquote s request matches to standard allow/deny rules.
If for some reason you need to avoid this check, you should call pluginlink->alwaysauth to do some dirty job, like establishing outgoing connection.
\par
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid16077654\charrsid4980816 typedef int (*AUTHFUNC)(struct clientparam * param);
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid16077654
\par is both authentication and authorization function. \lquote }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid16077654\charrsid16077654 struct clientparam}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid16077654
\rquote holds all information about client connection, including username (param->username) and password (param->password).
\par
\par Return value of 0 indicates successful authentication/authorization, 1}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid1600374 and 3}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid16077654 \endash
authorization }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid1600374 failed (access denied), use {\*\xmlopen\xmlns2{\factoidname metricconverter}{\xmlattr\xmlattrns0{\xmlattrname ProductID}{\xmlattrvalue 3 in}}}3 in{\*\xmlclose}
case you want to indicate access is explicitly denied and {\*\xmlopen\xmlns2{\factoidname metricconverter}{\xmlattr\xmlattrns0{\xmlattrname ProductID}{\xmlattrvalue 3 in}}}3 in{\*\xmlclose} case there is no matching rule. 4,5,6,7,8 \endash
authentication failed (e.g. username/password do not match). 4 indicates username }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid12806430 does not present in request and }{\rtlch\fcs1 \af0 \ltrch\fcs0
\lang1033\langfe1049\langnp1033\insrsid1600374 must be requested, if possible. 5 indicates username }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid12806430 found in request }{\rtlch\fcs1 \af0 \ltrch\fcs0
\lang1033\langfe1049\langnp1033\insrsid1600374 can not be found in user\rquote s database/list, 6,7,8 \endash username does not match password for different authentication types. 10 \endash user exceeded some limits, e.g. tr
affic. You may use some different code to indicate internal problems.}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid16077654
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid1600374
\par Example:
\par
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid1600374\charrsid1600374 int myauthfunc(struct clientparam *param);
\par struct auth myauth;
\par
\par myauth.desc = \'93myauth\'94;
\par myauth.authenticate = myauthfunc;
\par myauth.authorize = pluginlink->checkACL;
\par myauth->next = pluginlink->authfuncs->next;
\par pluginlink->authfuncs->next = &myauth;
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid1600374
\par Installs \'93myauthfunc\'94 as authentication function.}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid7235628 There is no need to add \lquote auth\rquote command processor for new authentication type, it\rquote
s processed by standard \lquote auth\rquote command processor.}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid12806430
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid7235628
\par {\listtext\tab}}\pard \ltrpar\ql \li0\ri0\widctlpar\jclisttab\tx360\wrapdefault\aspalpha\aspnum\faauto\ls4\ilvl2\adjustright\rin0\lin0\itap0\pararsid12806430 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid2296829 2.3.3 }{\rtlch\fcs1
\af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid12806430 Adding scheduled functions
\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid12806430 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid12806430
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid4980816 Scheduled functions are described by this structure:
\par
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid15928529\charrsid15236432 typedef enum \{NONE, MINUTELY, HOURLY, DAILY, WEEKLY, MONTHLY, ANNUALLY, NEVER\} ROTATION;
\par
\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid4980816 {\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid4980816\charrsid15236432 struct schedule \{
\par \tab struct schedule *next;
\par \tab ROTATION type;
\par \tab void *data;
\par \tab int (*function)(void *);
\par \tab time_t start_time;
\par \};
\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid12806430 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid4980816
\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid15928529 {\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid15928529\charrsid15236432 int (*function)(void *)}{\rtlch\fcs1
\af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid15928529 \endash scheduled function}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid15928529\charrsid4980816
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid15928529\charrsid15236432 void *data}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid15928529 \endash
this pointer will be passed as an argument to scheduled functions}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid15928529\charrsid4980816
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid15928529\charrsid15236432 ROTATION type}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid15928529 \endash
defines how often function is called (once in a minute, hour, etc).
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid15928529\charrsid15236432 start_time}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid15928529 \endash time to begin using of scheduled function
\par
\par Scheduled functions are called every \lquote type\rquote interval after start_time and also on reloading configuration and going to termination state.
\par
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid15236432 Schedule function r}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid15928529 eturn value of 1 means function must be
removed from the schedule. 3proxy doesn\rquote t free struct schedule.
\par
\par Schedule list can be empty. Pointer to schedule is pointed by }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid15928529\charrsid15236432 struct schedule ** schedule;}{\rtlch\fcs1 \af0 \ltrch\fcs0
\lang1033\langfe1049\langnp1033\insrsid15928529 in pluginlink.
\par
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid15236432 Example:}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid15928529
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid15236432
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid15236432\charrsid15236432 int myschedfunc(void * data);
\par struct schedule myschedule;
\par
\par myschedule.data = \'93somethinghere\'94;
\par myschedule.function = myschedfunc}{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid15236432 ;}{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid15236432\charrsid15236432
\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid12806430 {\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid15236432\charrsid15236432 myschedule.type = MINUTELY;}{\rtlch\fcs1
\af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid15928529\charrsid15236432
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid15236432\charrsid15236432 myschedule.starttime = 0;
\par myschedule.next = *pluginlink->schedule;
\par *pluginlink->schedule = myschedule;
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid15236432
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \ul\lang1033\langfe1049\langnp1033\insrsid15236432\charrsid15236432 NOTE:}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid15236432 time_t is different for different compilers.
Make sure to compile plugin and 3proxy with same compiler.
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid15928529
\par {\listtext\tab}}\pard \ltrpar\ql \li0\ri0\widctlpar\jclisttab\tx360\wrapdefault\aspalpha\aspnum\faauto\ls4\ilvl2\adjustright\rin0\lin0\itap0\pararsid4980816 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid4980816 2.3.4 Filters API
\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid4980816 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid4980816
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid15236432 3proxy has filters API, you can use, to process client request and data flowing through proxy. It should be noted, that currently 3proxy doesn\rquote
t provide filters with any useful data conversion, so, it\rquote s filter\rquote s task to find data in data flow. In case filter modifies some data, it\rquote s filter\rquote s task again to assure that everything\rquote s fine.}{\rtlch\fcs1 \af0
\ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid1771507 If you know some filtering API like MILTER, you will find 3proxy filters very same.}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid15236432
\par
\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid15236432 {\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid15236432\charrsid1771507 typedef enum \{
\par \tab PASS,
\par \tab CONTINUE,
\par \tab HANDLED,
\par \tab REJECT,
\par \tab REMOVE
\par \} FILTER_ACTION;
\par
\par typedef\tab void*\tab \tab FILTER_OPEN(void * idata, struct srvparam * param);
\par typedef\tab FILTER_ACTION \tab FILTER_CLIENT(void *fo, struct clientparam * param, void** fc);
\par typedef\tab FILTER_ACTION\tab FILTER_BUFFER(void *fc, struct clientparam * param, unsigned char ** buf_p, int * bufsize_p, int offset, int * length_p);
\par typedef\tab void\tab \tab FILTER_CLOSE(void *fo);
\par
\par struct filter \{
\par \tab struct filter * next;
\par \tab char * instance;
\par \tab void * data;
\par \tab FILTER_OPEN *filter_open;
\par \tab FILTER_CLIENT *filter_client;
\par \tab FILTER_BUFFER *filter_request;
\par \tab FILTER_BUFFER *filter_header_cli;
\par \tab FILTER_BUFFER *filter_header_srv;
\par \tab FILTER_BUFFER *filter_data_cli;
\par \tab FILTER_BUFFER *filter_data_srv;
\par \tab FILTER_CLOSE *filter_clear;
\par \tab FILTER_CLOSE *filter_close;
\par \};
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid15236432
\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid1771507 {\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid1771507\charrsid1771507 char * instance}{\rtlch\fcs1 \af0
\ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid1771507 \endash is some instance identifier. You can use it to find required filter in the list. 3proxy itself doesn\rquote t use this field.}{\rtlch\fcs1 \af0 \ltrch\fcs0
\lang1033\langfe1049\langnp1033\insrsid1771507\charrsid15236432
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid7013593
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid1771507\charrsid1771507 void * data}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid1771507 \endash this parameter is passed to filter_open function.
\par The rest are filtering functions. Section 1 explains where and then each filter is called.}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid7013593 data should not be NULL.}{\rtlch\fcs1 \af0 \ltrch\fcs0
\lang1033\langfe1049\langnp1033\insrsid1771507
\par
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid1771507\charrsid1986875 filter_open}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid1771507 must always be defined, if you want filter to be ever used. It
\rquote s called then new service is created and is given \'93data\'94 from struct filter and struct srvparam (parsed service configuration). If filter_op
en for some filter returns NULL, filter will not be used for this service. Non-NULL return value will be used as \'93fo\'94 parameter for every call to filter_client.
\par
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid1771507\charrsid1986875 filter_client}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid1771507 }{\rtlch\fcs1 \af0 \ltrch\fcs0
\lang1033\langfe1049\langnp1033\insrsid1986875 is called upon client connect (before any data is sent/received). It\rquote s good plac
e to filter client by IP (and is not good place to filter it by hostname, because this operation takes a long time, 3proxy will not be able to accept new connection). fo is a data pointer received from filter_open, param \endash
newly created clientparam structu
re, fc is return parameter filter_open must initialize, it will be used as an argument to FILTER_BUFFER functions. PASS return value means this filter will be used for this client request. CONTINUE says to install filters. On different values client conne
ction is closed and no client thread is created.}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid1771507\charrsid15236432
\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid15236432 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid1771507
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid1986875 f}{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid1986875\charrsid1771507 ilter_reques}{\rtlch\fcs1 \af0 \ltrch\fcs0
\i\lang1033\langfe1049\langnp1033\insrsid1986875 t, }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid1986875\charrsid1771507 filter_header_cli}{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid1986875 , }{
\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid1986875\charrsid1771507 filter_header_srv}{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid1986875 , }{\rtlch\fcs1 \af0 \ltrch\fcs0
\i\lang1033\langfe1049\langnp1033\insrsid1986875\charrsid1771507 filter_data_cli}{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid1986875 , }{\rtlch\fcs1 \af0 \ltrch\fcs0
\i\lang1033\langfe1049\langnp1033\insrsid1986875\charrsid1771507 filter_data_srv}{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid1986875 }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid1986875
are used to process request and data r}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid9981679 eceived from client and server.}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid1986875\charrsid1986875
\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid4980816 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid15236432
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid9981679\charrsid1771507 char ** buf_p}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid9981679 is a pointer to current buffer, }{\rtlch\fcs1 \af0 \ltrch\fcs0
\i\lang1033\langfe1049\langnp1033\insrsid9981679\charrsid1771507 int * bufsize_p}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid9981679 is a pointer to it\rquote s size. In case you change some data and it doesn\rquote
t fit to current buffer, you may allocate new buffer (with pluginlink->myalloc), copy data from old buffer, free old buffer (with pluginlink->myfree) and set new values for *}{\rtlch\fcs1 \af0 \ltrch\fcs0
\i\lang1033\langfe1049\langnp1033\insrsid9981679\charrsid1771507 buf_p}{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid9981679 }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid9981679 and }{\rtlch\fcs1 \af0
\ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid9981679 *}{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid9981679\charrsid1771507 bufsize_p}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid9981679 .
\par
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid9981679 int }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid9981679\charrsid1771507 * offset_p}{\rtlch\fcs1 \af0 \ltrch\fcs0
\lang1033\langfe1049\langnp1033\insrsid9981679 offset of the new data in the buffer, }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid9981679\charrsid1771507 int * length_p}{\rtlch\fcs1 \af0 \ltrch\fcs0
\lang1033\langfe1049\langnp1033\insrsid9981679 length of all data in the buffer. You should filter only (*length_p - *offset_p) characters starting from }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid9981679\charrsid9981679
(*buf_p + *offset_p)}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid9981679 .}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid9981679\charrsid9981679
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid9981679
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid9981679\charrsid1771507 filter_clear}{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid9981679 }{\rtlch\fcs1 \af0 \ltrch\fcs0
\lang1033\langfe1049\langnp1033\insrsid9981679 is called for each successfule filter_client}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid15609114 and should be used to free allocated resources}{\rtlch\fcs1 \af0 \ltrch\fcs0
\lang1033\langfe1049\langnp1033\insrsid9981679\charrsid9981679
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid9981679\charrsid9981679 filter_close}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid9981679 is called for each successful filter_open}{\rtlch\fcs1 \af0
\ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid15609114 for the same reason}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid9981679
\par
\par An example of filter API usage you can find in PCREPlugin (see plugins/}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid9981679\charrsid9981679 PCREPlugin}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid9981679 /
}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid9981679\charrsid9981679 pcre_plugin.c}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid9981679 ).
\par
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \ul\lang1033\langfe1049\langnp1033\insrsid15609114\charrsid15609114 Note}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid15609114 : if }{\rtlch\fcs1 \af0 \ltrch\fcs0
\lang1033\langfe1049\langnp1033\insrsid15609114\charrsid15609114 param->nooverwritefilter}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid15609114
is set for FILTER_BUFFER functions, filter may change data in the buffer, but must not change data length. This flag may be set, if data size if already known and is sent to the client. }{\rtlch\fcs1 \af0 \ltrch\fcs0
\lang1033\langfe1049\langnp1033\insrsid15609114\charrsid15609114
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid15609114\charrsid9981679
\par {\listtext\tab}}\pard \ltrpar\ql \li0\ri0\widctlpar\jclisttab\tx360\wrapdefault\aspalpha\aspnum\faauto\ls4\ilvl2\adjustright\rin0\lin0\itap0\pararsid4980816 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid4980816 2.3.5
Replacing log functions, traffic counting functions, bandwidth limitation functions
\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid4980816 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid4980816
\par }\pard \ltrpar\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid13909505 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid8326885
Log, traffic and bandwidth function can be directly replaced in any over place. All functions may be replaced in conf (pluginlink->conf->logfunc, pluginlink->conf->bandlim
func, pluginlink->conf->trafcountfunc). In this case, these functions will be used for services started after the changes are made. }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid2567226 l}{\rtlch\fcs1 \af0 \ltrch\fcs0
\lang1033\langfe1049\langnp1033\insrsid8326885 ogfunc may also be changed for }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid2567226 struct s}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid8326885
rvparam (e.g. within filter_open)}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid2567226 , bandlimfunc and trafcountfunc may be changed in struct clientparam for every client individually (e.g. within filter_client).}{\rtlch\fcs1
\af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid12806430
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid2567226
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid2567226\charrsid2567226 typedef void (*LOGFUNC)(struct clientparam * param, const unsigned char * test);
\par typedef void (*TRAFCOUNTFUNC)(struct clientparam * param); }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid2567226
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid2567226\charrsid2567226 typedef unsigned (*BANDLIMFUNC)(struct clientparam * param, unsigned nbytesin, unsigned nbytesout);
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid2567226
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid2567226\charrsid2567226 struct clientparam * param}{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid2567226 \endash }{\rtlch\fcs1 \af0 \ltrch\fcs0
\lang1033\langfe1049\langnp1033\insrsid2567226 information about client request}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid2567226\charrsid2567226
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid2567226\charrsid2567226 char * text}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid2567226 - text string (e.g. request)
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \i\lang1033\langfe1049\langnp1033\insrsid2567226\charrsid2567226 nbytesin, nbytesout}{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid2567226 \endash
number of bytes received from / send to server. bandlimfunc returns delay in milliseconds.
\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang1033\langfe1049\langnp1033\insrsid2567226\charrsid2567226
\par }}

259
doc/html/devel/devref.html Normal file
View File

@ -0,0 +1,259 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Style-Type" content="text/css">
<title>3proxy developer reference</title>
<style type="text/css">
span.s1 {text-decoration: underline}
ol {list-style-type: none}
ol.level1 {counter-reset: h1}
ol.level1 > li::before {content: counter(h1) ". "; counter-increment: h1; font-weight: bold}
ol.level2 {counter-reset: h2}
ol.level2 > li::before {content: counter(h1) "." counter(h2) " "; counter-increment: h2}
ol.level3 {counter-reset: h3}
ol.level3 > li::before {content: counter(h1) "." counter(h2) "." counter(h3) " "; counter-increment: h3}
pre {margin: 0.5em 0; padding: 0.5em; background: #f5f5f5; border: 1px solid #ddd}
code {font-family: monospace}
</style>
</head>
<body>
<h2>3proxy developer reference</h2>
<ol class="level1">
<li><b>Understanding Internal 3proxy structure</b>
<p>3proxy is implemented as multithread application. Server model is implemented as "one connection one thread". It means, for every client connection new thread is created. This model is effective enough under Windows, because it allows it avoid thread creation on asynchronous operations, yet under most POSIX systems this model can not be considered as most efficient. It's planned for (very far in future) release to implement more efficient model, where single thread can serve few clients.</p>
<ol class="level2">
<li>main thread
<p>3proxy begins with main thread. This thread parses configuration file and starts main loop. During configuration file parsing <code>struct extaparam conf;</code> structure is filled and service threads are started.</p>
<p>Main loop cycle takes approximately 1 second and does these tasks:</p>
<ul>
<li>re-reads configuration file, if necessary</li>
<li>performs scheduled tasks</li>
<li>monitors files ('monitor' command), approx. once in a minute</li>
<li>rotates main logfile</li>
<li>dumps counters to file, approx. once in a minute</li>
<li>performs termination, if required</li>
</ul>
<p>It's guaranteed every configuration and schedule command is executed from the same thread.</p>
<p>Main thread is implemented in <b>3proxy.c</b></p>
</li>
<li>service thread
<p>Service threads are started immediately, than service command (e.g. 'proxy' or 'socks') are found during configuration file parsing. Each command creates new thread. Thread does these tasks:</p>
<ul>
<li>parses service command arguments and fills <code>struct srvparam srv</code> structure with service configuration and <code>struct clientparam defparam</code> structure with default client configuration</li>
<li>initializes filters (filter_open)</li>
<li>creates and initializes listening service socket</li>
<li>enters into service loop</li>
<li>terminates filters (filter_close)</li>
</ul>
<p>service loop:</p>
<ul>
<li>checks for configuration reload (approximately every second), thread exits if configuration reloaded or 3proxy is in terminating state.</li>
<li>accepts client connection and creates <code>struct clientparam newparam</code> structure with client configuration</li>
<li>creates/checks client filters (filter_client)</li>
<li>creates client thread with newly created <code>struct clientparam newparam</code></li>
</ul>
<p>service threads are implemented in <b>proxymain.c</b></p>
<p>Please note: struct clientparam is freed and filter_clear is executed from different (client) thread.</p>
</li>
<li>client thread
<p>Client threads are started from service thread. Client thread:</p>
<ul>
<li>reads client request (except portmappers) with authentication information and request headers (if any).</li>
<li>filters request (if any) with filter_request</li>
<li>filters headers (if any) with filter_header_cli</li>
<li>performs authentication and authorization</li>
<li>established connection with server</li>
<li>sends request to server</li>
<li>filters server headers (if any)</li>
<li>maps client end server sockets to transmit data between client and server</li>
<li>logs request. Global counters are also updated on this operation</li>
<li>clears client filters (filter_clear)</li>
<li>frees <code>struct clientparam</code> data</li>
</ul>
<p>in some point client thread may loop to process few client requests from the same connection (e.g. HTTP 'established' connection in 'proxy').</p>
<p>Socket mapping does:</p>
<ul>
<li>caches data in internal client and server buffers</li>
<li>delays data transmit to limit bandwidth</li>
<li>performs data filtering (filter_data_cli / filter_data_srv)</li>
</ul>
<p>client threads are implemented in <b>proxy.c</b>, <b>socks.c</b>, <b>pop3p.c</b> etc.</p>
</li>
</ol>
</li>
<li><b>Hacking into 3proxy code with plugins</b>
<ol class="level2">
<li>What is 3proxy plugin
<p>3proxy plugin is any dynamic/shared library. There is no specific requirement for plugin, actually you can load any dynamic library with 'plugin' command. No linking with any libraries are required. However, to interoperate with 3proxy dynamic library must have an export function 3proxy may call to pass the structure with required information.</p>
<pre><code>typedef int (*PLUGINFUNC) (struct pluginlink *pluginlink, int argc, char** argv);</code></pre>
<p><code>struct pluginlink</code> is a structure with export information, explained later, argc and argv are argument counter and array of arguments of "plugin" command. Plugin should report it's status with integer return value. 0 is success, positive value indicates non-recoverable error, 3proxy do not parse rest of configuration and enters into termination state, negative value indicates recoverable value, 3proxy logs warning (if possible). In case of C++, all 3proxy functions/structures must be extern "C".</p>
<p>All 3proxy structures/functions descriptions are located in <b>structures.h</b></p>
</li>
<li>Understanding pluginlink structure
<p>Because there is no linking between 3proxy and plugin, all 3proxy functions and structures are passed with pluginlink structure. Pluginlink is actually a collection of pointers to 3proxy internal structures and functions. Because pluginlink is constantly extending, you should see it's definitions in <b>structures.h</b>.</p>
<p>most important are:</p>
<pre><code>struct symbol symbols;</code></pre>
<p>"symbols" is a kind of name/value export table, made as a list. It can be used by plugins to exchange information and functions between plugins, e.g. to export functions from one plugin to another, where pluginlink is useless, because it's static. It's quite simple:</p>
<pre><code>struct symbol {
struct symbol *next;
char * name;
void * value;
};</code></pre>
<p><code>name</code> is a name of function or structure</p>
<p><code>value</code> is it's value.</p>
<p>use <code>pluginlink-&gt;findbyname</code> function to lookup, e.g.</p>
<pre><code>anotherplugindata = pluginlink-&gt;findbyname("anotherplugindata");</code></pre>
<p>To export something from your plugin, add your structure to this list.</p>
<pre><code>struct extparam *conf;</code></pre>
<p>pointer to conf structure, it holds all current 3proxy configuration</p>
</li>
<li>How to get control within plugin
<p>There are few points you can get control for your plugin, after it's loaded with 'plugin' command.</p>
<ol class="level3">
<li>Adding configuration command processor with struct command structure
<p>A list of configuration file command, available from 3proxy.cfg is extendable. Each command is defined by <code>struct commands</code>:</p>
<pre><code>struct commands {
struct commands *next;
char * command;
int (* handler)(int argc, unsigned char ** argv);
int minargs;
int maxargs;
};</code></pre>
<p><code>struct commands *next</code> - next element in list</p>
<p><code>char * command</code> command name</p>
<p><code>int (* handler)(int argc, unsigned char ** argv)</code> command handler. It's called than 'command' is found in configuration files, argc is a number of arguments, counting command itself, argv is array of arguments.</p>
<p><code>minargs</code> minimum number of arguments command support (&gt;= 1)</p>
<p><code>maxargs</code> maximum number of arguments command support, 0 means infinity.</p>
<p>Handler return value of 0 indicates command is successfully processed. Positive return value indicates non-recoverable error, 3proxy enters termination state. Negative value indicates 3proxy to continue to process command list, it makes it possible to set few handlers for the same command.</p>
<p>A list of the command is pointed by <code>pluginlink-&gt;commandhandlers</code>; you must insert you command after first one (do not replace <code>pluginlink-&gt;commandhandlers</code>). It's guaranteed at least 1 dummy command is always present.</p>
<p>Example:</p>
<pre><code>int mycommandhandler(int argc, unsigned char **argv);
struct commands mycommand;
mycommand.command = "mycommand";
mycommand.handler = mycommandhandler;
mycommand.intargs = 1;
mycommand.intargs = 2;
mycommand.next = pluginslinks-&gt;commandhandlers-&gt;next;
pluginslink-&gt;commandhandlers-&gt;next = &amp;mycommand;</code></pre>
<p>Adds processor for "mycommand" command with zero on one arguments.</p>
<p>Adding configuration command is useful, if your plugin expects configuration data.</p>
</li>
<li>Adding authentication method with struct auth
<p>3proxy supports authentication and authorization. Authentication process determines user account (for example by username and password), authorization checks, if user account has a right to access given resource and optionally establishes a connection, if required.</p>
<p>'auth' command combines both authentication and authorization method. It's extandable with struct auth list:</p>
<pre><code>struct auth {
struct auth *next;
AUTHFUNC authenticate;
AUTHFUNC authorize;
char * desc;
};</code></pre>
<p><code>char * desc</code> name of authentication/authorization method</p>
<p><code>authenticate</code> name of authentication function</p>
<p><code>authorize</code> name of authorization function</p>
<p><code>pluginlink-&gt;authfuncs</code> points to list of authenticataction structures. Like above, new structure must be inserted after fiest one (or to the end of the list).</p>
<p>First, authentication is called, if authentication indicates OK status (return value 0), authorization is called. Normally, 'checkACL' (<code>pluginlink-&gt;checkACL</code>) is called as authorization function to check user's request matches to standard allow/deny rules. If for some reason you need to avoid this check, you should call <code>pluginlink-&gt;alwaysauth</code> to do some dirty job, like establishing outgoing connection.</p>
<pre><code>typedef int (*AUTHFUNC)(struct clientparam * param);</code></pre>
<p>is both authentication and authorization function. <code>struct clientparam</code> holds all information about client connection, including username (<code>param-&gt;username</code>) and password (<code>param-&gt;password</code>).</p>
<p>Return value of 0 indicates successful authentication/authorization, 1 and 3 authorization failed (access denied), use 3 in case you want to indicate access is explicitly denied and 3 in case there is no matching rule. 4,5,6,7,8 authentication failed (e.g. username/password do not match). 4 indicates username does not present in request and must be requested, if possible. 5 indicates username found in request can not be found in user's database/list, 6,7,8 username does not match password for different authentication types. 10 user exceeded some limits, e.g. traffic. You may use some different code to indicate internal problems.</p>
<p>Example:</p>
<pre><code>int myauthfunc(struct clientparam *param);
struct auth myauth;
myauth.desc = "myauth";
myauth.authenticate = myauthfunc;
myauth.authorize = pluginlink-&gt;checkACL;
myauth-&gt;next = pluginlink-&gt;authfuncs-&gt;next;
pluginlink-&gt;authfuncs-&gt;next = &amp;myauth;</code></pre>
<p>Installs "myauthfunc" as authentication function. There is no need to add 'auth' command processor for new authentication type, it's processed by standard 'auth' command processor.</p>
</li>
<li>Adding scheduled functions
<p>Scheduled functions are described by this structure:</p>
<pre><code>typedef enum {NONE, MINUTELY, HOURLY, DAILY, WEEKLY, MONTHLY, ANNUALLY, NEVER} ROTATION;
struct schedule {
struct schedule *next;
ROTATION type;
void *data;
int (*function)(void *);
time_t start_time;
};</code></pre>
<p><code>int (*function)(void *)</code> scheduled function</p>
<p><code>void *data</code> this pointer will be passed as an argument to scheduled functions</p>
<p><code>ROTATION type</code> defines how often function is called (once in a minute, hour, etc).</p>
<p><code>start_time</code> time to begin using of scheduled function</p>
<p>Scheduled functions are called every 'type' interval after start_time and also on reloading configuration and going to termination state.</p>
<p>Schedule function return value of 1 means function must be removed from the schedule. 3proxy doesn't free struct schedule.</p>
<p>Schedule list can be empty. Pointer to schedule is pointed by <code>struct schedule ** schedule;</code> in pluginlink.</p>
<p>Example:</p>
<pre><code>int myschedfunc(void * data);
struct schedule myschedule;
myschedule.data = "somethinghere";
myschedule.function = myschedfunc;
myschedule.type = MINUTELY;
myschedule.starttime = 0;
myschedule.next = *pluginlink-&gt;schedule;
*pluginlink-&gt;schedule = myschedule;</code></pre>
<p><span class="s1">NOTE:</span> time_t is different for different compilers. Make sure to compile plugin and 3proxy with same compiler.</p>
</li>
<li>Filters API
<p>3proxy has filters API, you can use, to process client request and data flowing through proxy. It should be noted, that currently 3proxy doesn't provide filters with any useful data conversion, so, it's filter's task to find data in data flow. In case filter modifies some data, it's filter's task again to assure that everything's fine. If you know some filtering API like MILTER, you will find 3proxy filters very same.</p>
<pre><code>typedef enum {
PASS,
CONTINUE,
HANDLED,
REJECT,
REMOVE
} FILTER_ACTION;
typedef void* FILTER_OPEN(void * idata, struct srvparam * param);
typedef FILTER_ACTION FILTER_CLIENT(void *fo, struct clientparam * param, void** fc);
typedef FILTER_ACTION FILTER_BUFFER(void *fc, struct clientparam * param, unsigned char ** buf_p, int * bufsize_p, int offset, int * length_p);
typedef void FILTER_CLOSE(void *fo);
struct filter {
struct filter * next;
char * instance;
void * data;
FILTER_OPEN *filter_open;
FILTER_CLIENT *filter_client;
FILTER_BUFFER *filter_request;
FILTER_BUFFER *filter_header_cli;
FILTER_BUFFER *filter_header_srv;
FILTER_BUFFER *filter_data_cli;
FILTER_BUFFER *filter_data_srv;
FILTER_CLOSE *filter_clear;
FILTER_CLOSE *filter_close;
};</code></pre>
<p><code>char * instance</code> is some instance identifier. You can use it to find required filter in the list. 3proxy itself doesn't use this field.</p>
<p><code>void * data</code> this parameter is passed to filter_open function. The rest are filtering functions. Section 1 explains where and then each filter is called. data should not be NULL.</p>
<p><code>filter_open</code> must always be defined, if you want filter to be ever used. It's called then new service is created and is given "data" from struct filter and struct srvparam (parsed service configuration). If filter_open for some filter returns NULL, filter will not be used for this service. Non-NULL return value will be used as "fo" parameter for every call to filter_client.</p>
<p><code>filter_client</code> is called upon client connect (before any data is sent/received). It's good place to filter client by IP (and is not good place to filter it by hostname, because this operation takes a long time, 3proxy will not be able to accept new connection). fo is a data pointer received from filter_open, param newly created clientparam structure, fc is return parameter filter_open must initialize, it will be used as an argument to FILTER_BUFFER functions. PASS return value means this filter will be used for this client request. CONTINUE says to install filters. On different values client connection is closed and no client thread is created.</p>
<p><code>filter_request, filter_header_cli, filter_header_srv, filter_data_cli, filter_data_srv</code> are used to process request and data received from client and server.</p>
<p><code>char ** buf_p</code> is a pointer to current buffer, <code>int * bufsize_p</code> is a pointer to it's size. In case you change some data and it doesn't fit to current buffer, you may allocate new buffer (with <code>pluginlink-&gt;myalloc</code>), copy data from old buffer, free old buffer (with <code>pluginlink-&gt;myfree</code>) and set new values for <code>*buf_p</code> and <code>*bufsize_p</code>.</p>
<p><code>int offset</code> offset of the new data in the buffer, <code>int * length_p</code> length of all data in the buffer. You should filter only <code>(*length_p - *offset_p)</code> characters starting from <code>(*buf_p + *offset_p)</code>.</p>
<p><code>filter_clear</code> is called for each successfule filter_client and should be used to free allocated resources</p>
<p><code>filter_close</code> is called for each successful filter_open for the same reason</p>
<p>An example of filter API usage you can find in PCREPlugin (see plugins/PCREPlugin/pcre_plugin.c).</p>
<p><span class="s1">Note</span>: if <code>param-&gt;nooverwritefilter</code> is set for FILTER_BUFFER functions, filter may change data in the buffer, but must not change data length. This flag may be set, if data size if already known and is sent to the client.</p>
</li>
<li>Replacing log functions, traffic counting functions, bandwidth limitation functions
<p>Log, traffic and bandwidth function can be directly replaced in any over place. All functions may be replaced in conf (<code>pluginlink-&gt;conf-&gt;logfunc</code>, <code>pluginlink-&gt;conf-&gt;bandlimfunc</code>, <code>pluginlink-&gt;conf-&gt;trafcountfunc</code>). In this case, these functions will be used for services started after the changes are made. logfunc may also be changed for struct srvparam (e.g. within filter_open), bandlimfunc and trafcountfunc may be changed in struct clientparam for every client individually (e.g. within filter_client).</p>
<pre><code>typedef void (*LOGFUNC)(struct clientparam * param, const unsigned char * test);
typedef void (*TRAFCOUNTFUNC)(struct clientparam * param);
typedef unsigned (*BANDLIMFUNC)(struct clientparam * param, unsigned nbytesin, unsigned nbytesout);</code></pre>
<p><code>struct clientparam * param</code> information about client request</p>
<p><code>char * text</code> - text string (e.g. request)</p>
<p><code>nbytesin, nbytesout</code> number of bytes received from / send to server. bandlimfunc returns delay in milliseconds.</p>
</li>
</ol>
</li>
</ol>
</li>
</ol>
</body>
</html>

View File

@ -33,8 +33,9 @@
<li><a href="#NAMES">How to resolve names through a parent proxy</a></li> <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="#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="#TLSPR">How to set up an SNI proxy (tlspr)</a></li>
<li><a href="#SSLPLUGIN">How to set up TLS/SSL with SSLPlugin (https proxy, mTLS)</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 SSLPlugin</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>
<li><A HREF="#AUTH">How to limit service access</A> <li><A HREF="#AUTH">How to limit service access</A>
<li><A HREF="#USERS">How to create a user list</A> <li><A HREF="#USERS">How to create a user list</A>
<li><A HREF="#ACL">How to limit user access to resources</A> <li><A HREF="#ACL">How to limit user access to resources</A>
@ -639,9 +640,12 @@ allow *
proxy proxy
</pre> </pre>
</p> </p>
<li><a name="SSLPLUGIN"><i>How to set up TLS/SSL with SSLPlugin (https proxy, mTLS)</i></a> <li><a name="SSLPLUGIN"><i>How to set up TLS/SSL (https proxy, mTLS)</i></a>
<p> <p>
SSLPlugin provides TLS/SSL support for 3proxy. It can be used to: Since version 0.9.7, SSL/TLS support is built into 3proxy when compiled with OpenSSL
(WITH_SSL). Previously available as SSLPlugin, the functionality is now integrated
into the main binary. The plugin line is no longer required.
SSL/TLS support can be used to:
<ul> <ul>
<li>Create an https:// proxy (TLS-encrypted connection between client and proxy)</li> <li>Create an https:// proxy (TLS-encrypted connection between client and proxy)</li>
<li>Implement MITM for TLS traffic inspection</li> <li>Implement MITM for TLS traffic inspection</li>
@ -654,7 +658,6 @@ SSLPlugin provides TLS/SSL support for 3proxy. It can be used to:
<br>To create an https:// proxy, you need a server certificate and key. The certificate must not be self-signed <br>To create an https:// proxy, you need a server certificate and key. The certificate must not be self-signed
and should contain Subject Alternative Names (SAN) for the proxy hostname/IP. and should contain Subject Alternative Names (SAN) for the proxy hostname/IP.
</p><pre> </p><pre>
plugin /path/to/SSLPlugin.ld.so ssl_plugin
ssl_server_cert /etc/3proxy/certs/server.crt ssl_server_cert /etc/3proxy/certs/server.crt
ssl_server_key /etc/3proxy/certs/server.key ssl_server_key /etc/3proxy/certs/server.key
ssl_serv ssl_serv
@ -670,7 +673,6 @@ Configure clients to use https://proxy-host:3129/ as the proxy URL.
<b>Client certificate authentication (mTLS):</b> <b>Client certificate authentication (mTLS):</b>
<br>To require clients to authenticate with a certificate, use ssl_server_verify and provide the CA certificate: <br>To require clients to authenticate with a certificate, use ssl_server_verify and provide the CA certificate:
</p><pre> </p><pre>
plugin /path/to/SSLPlugin.ld.so ssl_plugin
ssl_server_cert /etc/3proxy/certs/server.crt ssl_server_cert /etc/3proxy/certs/server.crt
ssl_server_key /etc/3proxy/certs/server.key ssl_server_key /etc/3proxy/certs/server.key
ssl_server_ca_file /etc/3proxy/certs/ca.crt ssl_server_ca_file /etc/3proxy/certs/ca.crt
@ -685,7 +687,6 @@ Only clients with a valid certificate signed by the CA can connect.
<b>MITM for TLS traffic inspection:</b> <b>MITM for TLS traffic inspection:</b>
<br>To intercept and decrypt TLS traffic, you need a CA certificate to generate spoofed server certificates: <br>To intercept and decrypt TLS traffic, you need a CA certificate to generate spoofed server certificates:
</p><pre> </p><pre>
plugin /path/to/SSLPlugin.ld.so ssl_plugin
ssl_server_ca_file /etc/3proxy/certs/ca.crt ssl_server_ca_file /etc/3proxy/certs/ca.crt
ssl_server_ca_key /etc/3proxy/certs/ca.key ssl_server_ca_key /etc/3proxy/certs/ca.key
ssl_client_verify ssl_client_verify
@ -703,7 +704,6 @@ Without ssl_client_verify, the proxy is vulnerable to MITM attacks.
<b>TLS client (connect to upstream via TLS):</b> <b>TLS client (connect to upstream via TLS):</b>
<br>To connect to upstream servers via TLS with client certificate authentication: <br>To connect to upstream servers via TLS with client certificate authentication:
</p><pre> </p><pre>
plugin /path/to/SSLPlugin.ld.so ssl_plugin
ssl_client_cert /etc/3proxy/certs/client.crt ssl_client_cert /etc/3proxy/certs/client.crt
ssl_client_key /etc/3proxy/certs/client.key ssl_client_key /etc/3proxy/certs/client.key
ssl_client_verify ssl_client_verify
@ -715,7 +715,6 @@ proxy -p3128
<b>Conditional TLS for parent proxy (ssl_client_mode 3):</b> <b>Conditional TLS for parent proxy (ssl_client_mode 3):</b>
<br>With ssl_client_mode 3, TLS handshake to parent proxy is performed only if the parent type ends with 's' (secure types). This allows mixing secure and non-secure parent proxies in the same configuration: <br>With ssl_client_mode 3, TLS handshake to parent proxy is performed only if the parent type ends with 's' (secure types). This allows mixing secure and non-secure parent proxies in the same configuration:
</p><pre> </p><pre>
plugin /path/to/SSLPlugin.ld.so ssl_plugin
ssl_server_cert /etc/3proxy/certs/server.crt ssl_server_cert /etc/3proxy/certs/server.crt
ssl_server_key /etc/3proxy/certs/server.key ssl_server_key /etc/3proxy/certs/server.key
ssl_client_mode 3 ssl_client_mode 3
@ -734,7 +733,7 @@ ssl_nocli
<p> <p>
This creates an HTTPS proxy (ssl_serv) that accepts TLS connections from clients. For parent proxy connections, user1's traffic goes through an https parent with TLS encryption (secure type), while user2's traffic goes through a regular socks5 parent without TLS. Secure parent types include: tcps, https, connects, connect+s, socks4s, socks5s, socks4+s, socks5+s, pop3s, smtps, ftps. This creates an HTTPS proxy (ssl_serv) that accepts TLS connections from clients. For parent proxy connections, user1's traffic goes through an https parent with TLS encryption (secure type), while user2's traffic goes through a regular socks5 parent without TLS. Secure parent types include: tcps, https, connects, connect+s, socks4s, socks5s, socks4+s, socks5+s, pop3s, smtps, ftps.
</p> </p>
<li><a name="CERTIFICATES"><i>How to create CA and certificates for SSLPlugin</i></a> <li><a name="CERTIFICATES"><i>How to create CA and certificates for SSL</i></a>
<p> <p>
<b>Creating a Certificate Authority (CA):</b> <b>Creating a Certificate Authority (CA):</b>
<br>For MITM or mTLS, you need a CA. Generate a CA private key and certificate: <br>For MITM or mTLS, you need a CA. Generate a CA private key and certificate:
@ -849,6 +848,65 @@ openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key \
openssl pkcs12 -export -out client.p12 -passout pass: \ openssl pkcs12 -export -out client.p12 -passout pass: \
-inkey client.key -in client.crt -certfile ca.crt -inkey client.key -in client.crt -certfile ca.crt
</pre> </pre>
<li><a name="PCRE"><i>How to use PCRE filtering (regular expressions)</i></a>
<p>
Since version 0.9.7, PCRE (Perl Compatible Regular Expressions) filtering is built into
3proxy when compiled with PCRE2 support (WITH_PCRE). Previously available as PCREPlugin,
the functionality is now integrated into the main binary. The plugin line is no longer required.
</p>
<p>
PCRE filtering can be used to create matching and replacement rules with regular expressions
for client requests, client and server headers, and client and server data.
</p>
<p>
<b>Commands:</b>
</p><pre>
pcre TYPE FILTER_ACTION REGEXP [ACE]
pcre_rewrite TYPE FILTER_ACTION REGEXP REWRITE_EXPRESSION [ACE]
pcre_extend FILTER_ACTION [ACE]
pcre_options OPTION1 [...]
</pre>
<p>
<ul>
<li><b>TYPE</b> - type of filtered data (comma-delimited list):
<ul>
<li><b>request</b> - content of the client's request (e.g., HTTP GET request string)
<li><b>cliheader</b> - content of the client request headers
<li><b>srvheader</b> - content of the server's reply headers
<li><b>clidata</b> - data received from the client (e.g., HTTP POST data)
<li><b>srvdata</b> - data received from the server (e.g., HTML page)
</ul>
<li><b>FILTER_ACTION</b> - action on match:
<ul>
<li><b>allow</b> - allow this request without checking the rest of the rules
<li><b>deny</b> - deny this request without checking the rest of the rules
<li><b>dunno</b> - continue with the rest of the rules (useful with pcre_rewrite)
</ul>
<li><b>REGEXP</b> - PCRE (Perl) regular expression. Use * if no regexp matching is required.
<li><b>REWRITE_EXPRESSION</b> - substitution string. May contain Perl-style substrings
$1, $2, etc. $0 means the whole matched string. \r and \n may be used to insert new lines.
<li><b>ACE</b> - access control entry (user names, source IPs, destination IPs, ports, etc.),
identical to allow/deny/bandlimin commands. The regular expression is only matched if the ACL
matches the connection data.
</ul>
</p>
<p>
<b>Examples:</b>
</p><pre>
# Block requests containing specific keywords for certain users
pcre request deny "porn|sex" user1,user2,user3 192.168.0.0/16
# Block responses with specific content type
pcre srvheader deny "Content-type: application"
# Replace content in both directions (censorship)
pcre_rewrite clidata,srvdata dunno "porn|sex|pussy" "***" baduser
pcre_extend deny * 192.168.0.1/16
</pre>
<p>
<b>Note:</b> Regular expressions don't require authentication and cannot replace
authentication and/or allow/deny ACLs.
</p>
<li><A NAME="AUTH">How to limit service access</A> <li><A NAME="AUTH">How to limit service access</A>
<p> <p>
First, always specify the internal interface to accept incoming connections with the First, always specify the internal interface to accept incoming connections with the

View File

@ -33,8 +33,9 @@
<li><a href="#NAMES">Как разрешать имена на родительском прокси?</a></li> <li><a href="#NAMES">Как разрешать имена на родительском прокси?</a></li>
<li><a href="#ISFTP">Как настроить FTP прокси?</a></li> <li><a href="#ISFTP">Как настроить FTP прокси?</a></li>
<li><a href="#TLSPR">Как настроить SNI proxy (tlspr)</a></li> <li><a href="#TLSPR">Как настроить SNI proxy (tlspr)</a></li>
<li><a href="#SSLPLUGIN">Как настроить TLS/SSL с помощью SSLPlugin (https прокси, mTLS)</a></li> <li><a href="#SSLPLUGIN">Как настроить TLS/SSL (https прокси, mTLS)</a></li>
<li><a href="#CERTIFICATES">Как создать CA и сертификаты для SSLPlugin</a></li> <li><a href="#CERTIFICATES">Как создать CA и сертификаты для SSL</a></li>
<li><a href="#PCRE">Как использовать PCRE-фильтрацию (регулярные выражения)</a></li>
<li><a href="#AUTH">Как ограничить доступ к службе</a> <li><a href="#AUTH">Как ограничить доступ к службе</a>
<li><a href="#USERS">Как создать список пользователей</a> <li><a href="#USERS">Как создать список пользователей</a>
<li><a href="#ACL">Как ограничить доступ пользователей к ресурсам</a> <li><a href="#ACL">Как ограничить доступ пользователей к ресурсам</a>
@ -648,9 +649,12 @@ proxy
</pre> </pre>
</p> </p>
<li><a name="SSLPLUGIN"><i>Как настроить TLS/SSL с помощью SSLPlugin (https прокси, mTLS)</i></a> <li><a name="SSLPLUGIN"><i>Как настроить TLS/SSL (https прокси, mTLS)</i></a>
<p> <p>
SSLPlugin обеспечивает поддержку TLS/SSL для 3proxy. Он может использоваться для: Начиная с версии 0.9.7 поддержка TLS/SSL встроена в 3proxy при компиляции с OpenSSL
(WITH_SSL). Ранее доступная как SSLPlugin, функциональность теперь интегрирована
в основной бинарный файл. Строка plugin больше не нужна.
TLS/SSL может использоваться для:
<ul> <ul>
<li>Создания https:// прокси (TLS-шифрованное соединение между клиентом и прокси)</li> <li>Создания https:// прокси (TLS-шифрованное соединение между клиентом и прокси)</li>
<li>Реализации MITM для инспекции TLS-трафика</li> <li>Реализации MITM для инспекции TLS-трафика</li>
@ -663,7 +667,6 @@ SSLPlugin обеспечивает поддержку TLS/SSL для 3proxy. О
<br>Для создания https:// прокси требуется сертификат и ключ сервера. Сертификат не должен быть самоподписанным <br>Для создания https:// прокси требуется сертификат и ключ сервера. Сертификат не должен быть самоподписанным
и должен содержать альтернативные имена (SAN) для имени хоста/IP прокси. и должен содержать альтернативные имена (SAN) для имени хоста/IP прокси.
</p><pre> </p><pre>
plugin /path/to/SSLPlugin.ld.so ssl_plugin
ssl_server_cert /etc/3proxy/certs/server.crt ssl_server_cert /etc/3proxy/certs/server.crt
ssl_server_key /etc/3proxy/certs/server.key ssl_server_key /etc/3proxy/certs/server.key
ssl_serv ssl_serv
@ -679,7 +682,6 @@ proxy -p3128
<b>Аутентификация по клиентскому сертификату (mTLS):</b> <b>Аутентификация по клиентскому сертификату (mTLS):</b>
<br>Чтобы требовать от клиентов аутентификацию по сертификату, используйте ssl_server_verify и укажите CA-сертификат: <br>Чтобы требовать от клиентов аутентификацию по сертификату, используйте ssl_server_verify и укажите CA-сертификат:
</p><pre> </p><pre>
plugin /path/to/SSLPlugin.ld.so ssl_plugin
ssl_server_cert /etc/3proxy/certs/server.crt ssl_server_cert /etc/3proxy/certs/server.crt
ssl_server_key /etc/3proxy/certs/server.key ssl_server_key /etc/3proxy/certs/server.key
ssl_server_ca_file /etc/3proxy/certs/ca.crt ssl_server_ca_file /etc/3proxy/certs/ca.crt
@ -694,7 +696,6 @@ proxy -p3129
<b>MITM для инспекции TLS-трафика:</b> <b>MITM для инспекции TLS-трафика:</b>
<br>Для перехвата и расшифровки TLS-трафика требуется CA-сертификат для генерации подделанных серверных сертификатов: <br>Для перехвата и расшифровки TLS-трафика требуется CA-сертификат для генерации подделанных серверных сертификатов:
</p><pre> </p><pre>
plugin /path/to/SSLPlugin.ld.so ssl_plugin
ssl_server_ca_file /etc/3proxy/certs/ca.crt ssl_server_ca_file /etc/3proxy/certs/ca.crt
ssl_server_ca_key /etc/3proxy/certs/ca.key ssl_server_ca_key /etc/3proxy/certs/ca.key
ssl_client_verify ssl_client_verify
@ -712,7 +713,6 @@ CA-сертификат должен быть доверенным для кли
<b>TLS-клиент (соединение с вышестоящим сервером через TLS):</b> <b>TLS-клиент (соединение с вышестоящим сервером через TLS):</b>
<br>Для соединения с вышестоящими серверами через TLS с аутентификацией по клиентскому сертификату: <br>Для соединения с вышестоящими серверами через TLS с аутентификацией по клиентскому сертификату:
</p><pre> </p><pre>
plugin /path/to/SSLPlugin.ld.so ssl_plugin
ssl_client_cert /etc/3proxy/certs/client.crt ssl_client_cert /etc/3proxy/certs/client.crt
ssl_client_key /etc/3proxy/certs/client.key ssl_client_key /etc/3proxy/certs/client.key
ssl_client_verify ssl_client_verify
@ -724,7 +724,6 @@ proxy -p3128
<b>Условное TLS для parent прокси (ssl_client_mode 3):</b> <b>Условное TLS для parent прокси (ssl_client_mode 3):</b>
<br>При ssl_client_mode 3 TLS-рукопожатие с родительским прокси выполняется только если тип parent прокси заканчивается на 's' (защищённые типы). Это позволяет смешивать защищённые и незащищённые родительские прокси в одной конфигурации: <br>При ssl_client_mode 3 TLS-рукопожатие с родительским прокси выполняется только если тип parent прокси заканчивается на 's' (защищённые типы). Это позволяет смешивать защищённые и незащищённые родительские прокси в одной конфигурации:
</p><pre> </p><pre>
plugin /path/to/SSLPlugin.ld.so ssl_plugin
ssl_server_cert /etc/3proxy/certs/server.crt ssl_server_cert /etc/3proxy/certs/server.crt
ssl_server_key /etc/3proxy/certs/server.key ssl_server_key /etc/3proxy/certs/server.key
ssl_client_mode 3 ssl_client_mode 3
@ -743,7 +742,7 @@ ssl_nocli
<p> <p>
Создаётся HTTPS-прокси (ssl_serv), принимающий TLS-соединения от клиентов. Для соединений с родительским прокси трафик user1 идёт через https родитель с TLS-шифрованием (защищённый тип), а трафик user2 — через обычный socks5 родитель без TLS. Защищённые типы parent прокси: tcps, https, connects, connect+s, socks4s, socks5s, socks4+s, socks5+s, pop3s, smtps, ftps. Создаётся HTTPS-прокси (ssl_serv), принимающий TLS-соединения от клиентов. Для соединений с родительским прокси трафик user1 идёт через https родитель с TLS-шифрованием (защищённый тип), а трафик user2 — через обычный socks5 родитель без TLS. Защищённые типы parent прокси: tcps, https, connects, connect+s, socks4s, socks5s, socks4+s, socks5+s, pop3s, smtps, ftps.
</p> </p>
<li><a name="CERTIFICATES"><i>Как создать CA и сертификаты для SSLPlugin</i></a> <li><a name="CERTIFICATES"><i>Как создать CA и сертификаты для SSL</i></a>
<p> <p>
<b>Создание удостоверяющего центра (CA):</b> <b>Создание удостоверяющего центра (CA):</b>
<br>Для MITM или mTLS требуется CA. Сгенерируйте закрытый ключ CA и сертификат: <br>Для MITM или mTLS требуется CA. Сгенерируйте закрытый ключ CA и сертификат:
@ -859,6 +858,66 @@ openssl pkcs12 -export -out client.p12 -passout pass: \
-inkey client.key -in client.crt -certfile ca.crt -inkey client.key -in client.crt -certfile ca.crt
</pre> </pre>
<li><a name="PCRE"><i>Как использовать PCRE-фильтрацию (регулярные выражения)</i></a>
<p>
Начиная с версии 0.9.7 фильтрация PCRE встроена в 3proxy при компиляции с поддержкой
PCRE2 (WITH_PCRE). Ранее доступная как PCREPlugin, функциональность теперь интегрирована
в основной бинарный файл. Строка plugin больше не нужна.
</p>
<p>
PCRE-фильтрация может использоваться для создания правил поиска и замены с регулярными
выражениями для запросов клиентов, заголовков клиента и сервера, а также данных.
</p>
<p>
<b>Команды:</b>
</p><pre>
pcre TYPE FILTER_ACTION REGEXP [ACE]
pcre_rewrite TYPE FILTER_ACTION REGEXP REWRITE_EXPRESSION [ACE]
pcre_extend FILTER_ACTION [ACE]
pcre_options OPTION1 [...]
</pre>
<p>
<ul>
<li><b>TYPE</b> - тип фильтруемых данных (список через запятую):
<ul>
<li><b>request</b> - содержимое запроса клиента (например, строка HTTP GET-запроса)
<li><b>cliheader</b> - содержимое заголовков запроса клиента
<li><b>srvheader</b> - содержимое заголовков ответа сервера
<li><b>clidata</b> - данные полученные от клиента (например, данные POST-запроса)
<li><b>srvdata</b> - данные полученные от сервера (например, HTML-страница)
</ul>
<li><b>FILTER_ACTION</b> - действие при совпадении:
<ul>
<li><b>allow</b> - разрешить запрос без проверки остальных правил
<li><b>deny</b> - запретить запрос без проверки остальных правил
<li><b>dunno</b> - продолжить проверку правил (полезно для pcre_rewrite)
</ul>
<li><b>REGEXP</b> - регулярное выражение PCRE (Perl). Используйте * если проверка не требуется.
<li><b>REWRITE_EXPRESSION</b> - строка замены. Может содержать Perl-подстановки
$1, $2 и т.д. $0 - вся найденная подстрока. \r и \n для вставки новых строк.
<li><b>ACE</b> - элемент списка контроля доступа (имена пользователей, IP источника,
IP назначения, порты и т.д.), аналогичный командам allow/deny/bandlimin.
Регулярное выражение проверяется только при совпадении ACL с данными соединения.
</ul>
</p>
<p>
<b>Примеры:</b>
</p><pre>
# Блокировать запросы с определёнными ключевыми словами для некоторых пользователей
pcre request deny "porn|sex" user1,user2,user3 192.168.0.0/16
# Блокировать ответы с определённым content-type
pcre srvheader deny "Content-type: application"
# Замена содержимого в обоих направлениях (цензура)
pcre_rewrite clidata,srvdata dunno "porn|sex|pussy" "***" baduser
pcre_extend deny * 192.168.0.1/16
</pre>
<p>
<b>Примечание:</b> Регулярные выражения не требуют авторизации и не могут заменить
авторизацию и/или ACL allow/deny.
</p>
<li><a name="AUTH"><i>Как ограничить доступ к службе</i></a> <li><a name="AUTH"><i>Как ограничить доступ к службе</i></a>
<p> <p>
Во-первых, для ограничения доступа необходимо указать внутренний интерфейс, Во-первых, для ограничения доступа необходимо указать внутренний интерфейс,

View File

@ -3,7 +3,9 @@
<a href="highload.html">Optimizing 3proxy for high loads</a><br> <a href="highload.html">Optimizing 3proxy for high loads</a><br>
<a href="howtoe.html">How To (English, very incomplete)</a><br> <a href="howtoe.html">How To (English, very incomplete)</a><br>
<a href="howtor.html">How To (Russian)</a><br> <a href="howtor.html">How To (Russian)</a><br>
<a href="devref.html">Developer reference</a><br>
<h3>Man pages:</h3> <h3>Man pages:</h3>
<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/3proxy.8.html">3proxy.8</A>
<br><A HREF="man8/ftppr.8.html">ftppr.8</A> <br><A HREF="man8/ftppr.8.html">ftppr.8</A>
<br><A HREF="man8/pop3p.8.html">pop3p.8</A> <br><A HREF="man8/pop3p.8.html">pop3p.8</A>
@ -13,5 +15,5 @@
<br><A HREF="man8/tcppm.8.html">tcppm.8</A> <br><A HREF="man8/tcppm.8.html">tcppm.8</A>
<br><A HREF="man8/tlspr.8.html">tlspr.8</A> <br><A HREF="man8/tlspr.8.html">tlspr.8</A>
<br><A HREF="man8/udppm.8.html">udppm.8</A> <br><A HREF="man8/udppm.8.html">udppm.8</A>
<br><A HREF="man3/3proxy.cfg.3.html">3proxy.cfg.3</A> <br><A HREF="man5/3proxy.cfg.5.html">3proxy.cfg.5</A>
</body></html> </body></html>

View File

@ -15,7 +15,6 @@
<a href="#FILES">FILES</a><br> <a href="#FILES">FILES</a><br>
<a href="#BUGS">BUGS</a><br> <a href="#BUGS">BUGS</a><br>
<a href="#SEE ALSO">SEE ALSO</a><br> <a href="#SEE ALSO">SEE ALSO</a><br>
<a href="#TRIVIA">TRIVIA</a><br>
<a href="#AUTHORS">AUTHORS</a><br> <a href="#AUTHORS">AUTHORS</a><br>
<hr> <hr>
@ -195,27 +194,18 @@ to <b>3proxy@3proxy.org</b></p>
</h2> </h2>
<p style="margin-left:6%; margin-top: 1em">3proxy.cfg(3), <p style="margin-left:6%; margin-top: 1em">3proxy.cfg(5),
proxy(8), ftppr(8), socks(8), pop3p(8), tcppm(8), udppm(8), proxy(8), ftppr(8), socks(8), pop3p(8), tcppm(8), udppm(8),
kill(1), syslogd(8), <br> kill(1), syslogd(8), <br>
https://3proxy.org/</p> https://3proxy.org/</p>
<h2>TRIVIA
<a name="TRIVIA"></a>
</h2>
<p style="margin-left:6%; margin-top: 1em">3APA3A is
pronounced as ``zaraza&acute;&acute;.</p>
<h2>AUTHORS <h2>AUTHORS
<a name="AUTHORS"></a> <a name="AUTHORS"></a>
</h2> </h2>
<p style="margin-left:6%; margin-top: 1em">3proxy is <p style="margin-left:6%; margin-top: 1em">3proxy is
designed by Vladimir 3APA3A Dubrovin designed by Vladimir Dubrovin &lt;vlad@3proxy.org&gt;</p>
(<i>3proxy@3proxy.org</i>)</p>
<hr> <hr>
</body> </body>
</html> </html>

View File

@ -0,0 +1,167 @@
<!-- Creator : groff version 1.24.1 -->
<html>
<head>
</head>
<body>
<h1 align="center">3proxy_crypt</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="#EXAMPLE">EXAMPLE</a><br>
<a href="#NOTES">NOTES</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>3proxy_crypt</b>
- utility to generate encrypted passwords for 3proxy</p>
<h2>SYNOPSIS
<a name="SYNOPSIS"></a>
</h2>
<p style="margin-left:6%; margin-top: 1em"><b>3proxy_crypt</b>
<i>password</i> <b><br>
3proxy_crypt</b> <i>salt password</i></p>
<h2>DESCRIPTION
<a name="DESCRIPTION"></a>
</h2>
<p style="margin-left:6%; margin-top: 1em"><i><b>3proxy_crypt</b></i>
is a utility to generate encrypted password hashes for use
with 3proxy configuration. Encrypted passwords allow the
system to avoid storing passwords in cleartext in
configuration files.</p>
<p style="margin-left:6%; margin-top: 1em">When invoked
with a single argument, it produces an NT password hash
(MD4-based, suitable for NTLM authentication). The output is
prefixed with <b>NT:</b>.</p>
<p style="margin-left:6%; margin-top: 1em">When invoked
with two arguments (salt and password), it produces a
BLAKE2b password hash. The salt length is limited to 64
characters. The output is prefixed with <b>CR:</b>.</p>
<p style="margin-left:6%; margin-top: 1em">The resulting
hash can be used in the 3proxy configuration file with the
<b>users</b> directive instead of a cleartext password.</p>
<h2>OPTIONS
<a name="OPTIONS"></a>
</h2>
<p style="margin-left:6%; margin-top: 1em"><i>password</i></p>
<p style="margin-left:15%;">Cleartext password to
encrypt.</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="5%">
<p><i>salt</i></p></td>
<td width="4%"></td>
<td width="65%">
<p>Salt string for BLAKE2b hashing (max 64 characters).</p></td>
<td width="20%">
</td></tr>
</table>
<h2>EXAMPLE
<a name="EXAMPLE"></a>
</h2>
<p style="margin-left:6%; margin-top: 1em">Generate NT
password hash:</p>
<p style="margin-left:15%;">3proxy_crypt
MySecretPassword</p>
<p style="margin-left:6%;">Result:</p>
<p style="margin-left:15%;">NT:3F7E6D8D96E8E7A9B0C1D2E3F4A5B6C7</p>
<p style="margin-left:6%;">Generate BLAKE2b password hash
with salt:</p>
<p style="margin-left:15%;">3proxy_crypt MySalt
MySecretPassword</p>
<p style="margin-left:6%;">Result:</p>
<p style="margin-left:15%;">CR:$3$MySalt$...</p>
<p style="margin-left:6%;">Using in 3proxy.cfg:</p>
<p style="margin-left:15%;">users
user1:CR:$3$MySalt$...</p>
<h2>NOTES
<a name="NOTES"></a>
</h2>
<p style="margin-left:6%; margin-top: 1em">The NT hash uses
the RSA MD4 Message-Digest Algorithm. The BLAKE2b hash uses
the BLAKE2 cryptographic hash function.</p>
<p style="margin-left:6%; margin-top: 1em">When a password
hash is prefixed with <b>NT:</b> or <b>CR:</b>, 3proxy uses
the corresponding algorithm to verify passwords instead of
comparing cleartext strings.</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),
3proxy.cfg(5), <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

@ -116,23 +116,45 @@ authentication.</p> </td></tr>
the interface the proxy should initiate connections from. By the interface the proxy should initiate connections from. By
default, the system will decide which address to use in default, the system will decide which address to use in
accordance with the routing table.</p></td></tr> 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"> <tr valign="top" align="left">
<td width="6%"></td> <td width="6%"></td>
<td width="3%"> <td width="3%">
<p style="margin-top: 1em"><b>-i</b></p></td> <p><b>-i</b></p></td>
<td width="6%"></td> <td width="6%"></td>
<td width="85%"> <td width="85%">
<p style="margin-top: 1em">Internal address. IP address the <p>Internal address. IP address the proxy accepts
proxy accepts connections to. By default, connections to any connections to. By default, connections to any interface are
interface are accepted. It&acute;s usually unsafe. Unix accepted. It&acute;s usually unsafe. Unix domain sockets can
domain sockets can be specified with be specified with <i>-iunix:/path/to/socket</i> syntax
<i>-iunix:/path/to/socket</i> syntax (e.g., (e.g., -iunix:/var/run/ftppr.sock). On Linux, abstract
-iunix:/var/run/ftppr.sock). On Linux, abstract sockets use sockets use <i>-iunix:@socketname</i> syntax.</p></td></tr>
<i>-iunix:@socketname</i> syntax.</p></td></tr>
<tr valign="top" align="left"> <tr valign="top" align="left">
<td width="6%"></td> <td width="6%"></td>
<td width="3%"> <td width="3%">
@ -198,7 +220,7 @@ with FTP proxy support, configure <i>internal_ip</i> and
FTP proxy support, use <i>internal_ip</i> and <i>port</i> as FTP proxy support, use <i>internal_ip</i> and <i>port</i> as
the FTP server. The address of the real FTP server must be the FTP server. The address of the real FTP server must be
configured as a part of the FTP username. The format for the configured as a part of the FTP username. The format for the
username is <i>username</i><b>@</b><i>server</i>, where username is <i>username</i>@<i>server</i>, where
<i>server</i> is the address of the FTP server and <i>server</i> is the address of the FTP server and
<i>username</i> is the user&acute;s login on this FTP <i>username</i> is the user&acute;s login on this FTP
server. The login itself may contain an &acute;@&acute; server. The login itself may contain an &acute;@&acute;
@ -229,8 +251,7 @@ https://3proxy.org/</p>
<p style="margin-left:6%; margin-top: 1em">3proxy is <p style="margin-left:6%; margin-top: 1em">3proxy is
designed by Vladimir 3APA3A Dubrovin designed by Vladimir Dubrovin &lt;vlad@3proxy.org&gt;</p>
(<i>3proxy@3proxy.org</i>)</p>
<hr> <hr>
</body> </body>
</html> </html>

View File

@ -116,23 +116,45 @@ authentication.</p> </td></tr>
the interface the proxy should initiate connections from. By the interface the proxy should initiate connections from. By
default, the system will decide which address to use in default, the system will decide which address to use in
accordance with the routing table.</p></td></tr> 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"> <tr valign="top" align="left">
<td width="6%"></td> <td width="6%"></td>
<td width="3%"> <td width="3%">
<p style="margin-top: 1em"><b>-i</b></p></td> <p><b>-i</b></p></td>
<td width="6%"></td> <td width="6%"></td>
<td width="85%"> <td width="85%">
<p style="margin-top: 1em">Internal address. IP address the <p>Internal address. IP address the proxy accepts
proxy accepts connections to. By default, connections to any connections to. By default, connections to any interface are
interface are accepted. It&acute;s usually unsafe. Unix accepted. It&acute;s usually unsafe. Unix domain sockets can
domain sockets can be specified with be specified with <i>-iunix:/path/to/socket</i> syntax
<i>-iunix:/path/to/socket</i> syntax (e.g., (e.g., -iunix:/var/run/pop3p.sock). On Linux, abstract
-iunix:/var/run/pop3p.sock). On Linux, abstract sockets use sockets use <i>-iunix:@socketname</i> syntax.</p></td></tr>
<i>-iunix:@socketname</i> syntax.</p></td></tr>
<tr valign="top" align="left"> <tr valign="top" align="left">
<td width="6%"></td> <td width="6%"></td>
<td width="3%"> <td width="3%">
@ -196,8 +218,8 @@ MUA (Mail User Agent) with POP3 support. Set the client to
use <i>internal_ip</i> and <i>port</i> as a POP3 server. The use <i>internal_ip</i> and <i>port</i> as a POP3 server. The
address of the real POP3 server must be configured as a part address of the real POP3 server must be configured as a part
of the POP3 username. The format for the username is of the POP3 username. The format for the username is
<i>username</i><b>@</b><i>server</i>, where <i>server</i> is <i>username</i>@<i>server</i>, where <i>server</i> is the
the address of the POP3 server and <i>username</i> is the address of the POP3 server and <i>username</i> is the
user&acute;s login on this POP3 server. The login itself may user&acute;s login on this POP3 server. The login itself may
contain an &acute;@&acute; sign. Only cleartext contain an &acute;@&acute; sign. Only cleartext
authentication is supported, because challenge-response authentication is supported, because challenge-response
@ -229,8 +251,7 @@ https://3proxy.org/</p>
<p style="margin-left:6%; margin-top: 1em">3proxy is <p style="margin-left:6%; margin-top: 1em">3proxy is
designed by Vladimir 3APA3A Dubrovin designed by Vladimir Dubrovin &lt;vlad@3proxy.org&gt;</p>
(<i>3proxy@3proxy.org</i>)</p>
<hr> <hr>
</body> </body>
</html> </html>

View File

@ -55,11 +55,11 @@ support.</p>
cellspacing="0" cellpadding="0"> cellspacing="0" cellpadding="0">
<tr valign="top" align="left"> <tr valign="top" align="left">
<td width="6%"></td> <td width="6%"></td>
<td width="4%"> <td width="3%">
<p style="margin-top: 1em"><b>-I</b></p></td> <p style="margin-top: 1em"><b>-I</b></p></td>
<td width="5%"></td> <td width="6%"></td>
<td width="85%"> <td width="85%">
@ -67,11 +67,11 @@ support.</p>
only.</p> </td></tr> only.</p> </td></tr>
<tr valign="top" align="left"> <tr valign="top" align="left">
<td width="6%"></td> <td width="6%"></td>
<td width="4%"> <td width="3%">
<p style="margin-top: 1em"><b>-d</b></p></td> <p style="margin-top: 1em"><b>-d</b></p></td>
<td width="5%"></td> <td width="6%"></td>
<td width="85%"> <td width="85%">
@ -79,11 +79,11 @@ only.</p> </td></tr>
console and run in the background.</p></td></tr> console and run in the background.</p></td></tr>
<tr valign="top" align="left"> <tr valign="top" align="left">
<td width="6%"></td> <td width="6%"></td>
<td width="4%"> <td width="3%">
<p style="margin-top: 1em"><b>-t</b></p></td> <p style="margin-top: 1em"><b>-t</b></p></td>
<td width="5%"></td> <td width="6%"></td>
<td width="85%"> <td width="85%">
@ -91,11 +91,11 @@ console and run in the background.</p></td></tr>
start/stop/accept error records.</p></td></tr> start/stop/accept error records.</p></td></tr>
<tr valign="top" align="left"> <tr valign="top" align="left">
<td width="6%"></td> <td width="6%"></td>
<td width="4%"> <td width="3%">
<p style="margin-top: 1em"><b>-u</b></p></td> <p style="margin-top: 1em"><b>-u</b></p></td>
<td width="5%"></td> <td width="6%"></td>
<td width="85%"> <td width="85%">
@ -103,11 +103,11 @@ start/stop/accept error records.</p></td></tr>
authentication</p> </td></tr> authentication</p> </td></tr>
<tr valign="top" align="left"> <tr valign="top" align="left">
<td width="6%"></td> <td width="6%"></td>
<td width="4%"> <td width="3%">
<p style="margin-top: 1em"><b>-e</b></p></td> <p style="margin-top: 1em"><b>-e</b></p></td>
<td width="5%"></td> <td width="6%"></td>
<td width="85%"> <td width="85%">
@ -115,23 +115,45 @@ authentication</p> </td></tr>
the interface the proxy should initiate connections from. By the interface the proxy should initiate connections from. By
default, the system will decide which address to use in default, the system will decide which address to use in
accordance with the routing table.</p></td></tr> 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"> <tr valign="top" align="left">
<td width="6%"></td> <td width="6%"></td>
<td width="4%"> <td width="4%">
<p style="margin-top: 1em"><b>-i</b></p></td> <p><b>-i</b></p></td>
<td width="5%"></td> <td width="5%"></td>
<td width="85%"> <td width="85%">
<p style="margin-top: 1em">Internal address. IP address the <p>Internal address. IP address the proxy accepts
proxy accepts connections to. By default, connections to any connections to. By default, connections to any interface are
interface are accepted. It&acute;s usually unsafe. Unix accepted. It&acute;s usually unsafe. Unix domain sockets can
domain sockets can be specified with be specified with <i>-iunix:/path/to/socket</i> syntax
<i>-iunix:/path/to/socket</i> syntax (e.g., (e.g., -iunix:/var/run/proxy.sock). On Linux, abstract
-iunix:/var/run/proxy.sock). On Linux, abstract sockets use sockets use <i>-iunix:@socketname</i> syntax.</p></td></tr>
<i>-iunix:@socketname</i> syntax.</p></td></tr>
<tr valign="top" align="left"> <tr valign="top" align="left">
<td width="6%"></td> <td width="6%"></td>
<td width="4%"> <td width="4%">
@ -234,8 +256,7 @@ https://3proxy.org/</p>
<p style="margin-left:6%; margin-top: 1em">3proxy is <p style="margin-left:6%; margin-top: 1em">3proxy is
designed by Vladimir 3APA3A Dubrovin designed by Vladimir Dubrovin &lt;vlad@3proxy.org&gt;</p>
(<i>3proxy@3proxy.org</i>)</p>
<hr> <hr>
</body> </body>
</html> </html>

View File

@ -116,23 +116,45 @@ authentication.</p> </td></tr>
the interface the proxy should initiate connections from. By the interface the proxy should initiate connections from. By
default, the system will decide which address to use in default, the system will decide which address to use in
accordance with the routing table.</p></td></tr> 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"> <tr valign="top" align="left">
<td width="6%"></td> <td width="6%"></td>
<td width="3%"> <td width="3%">
<p style="margin-top: 1em"><b>-i</b></p></td> <p><b>-i</b></p></td>
<td width="6%"></td> <td width="6%"></td>
<td width="85%"> <td width="85%">
<p style="margin-top: 1em">Internal address. IP address the <p>Internal address. IP address the proxy accepts
proxy accepts connections to. By default, connections to any connections to. By default, connections to any interface are
interface are accepted. It&acute;s usually unsafe. Unix accepted. It&acute;s usually unsafe. Unix domain sockets can
domain sockets can be specified with be specified with <i>-iunix:/path/to/socket</i> syntax
<i>-iunix:/path/to/socket</i> syntax (e.g., (e.g., -iunix:/var/run/smtpp.sock). On Linux, abstract
-iunix:/var/run/smtpp.sock). On Linux, abstract sockets use sockets use <i>-iunix:@socketname</i> syntax.</p></td></tr>
<i>-iunix:@socketname</i> syntax.</p></td></tr>
<tr valign="top" align="left"> <tr valign="top" align="left">
<td width="6%"></td> <td width="6%"></td>
<td width="3%"> <td width="3%">
@ -196,7 +218,7 @@ MUA (Mail User Agent) with SMTP authentication support. Set
the client to use <i>internal_ip</i> and <i>port</i> as an the client to use <i>internal_ip</i> and <i>port</i> as an
SMTP server. The address of the real SMTP server must be SMTP server. The address of the real SMTP server must be
configured as a part of the SMTP username. The format for configured as a part of the SMTP username. The format for
the username is <i>username</i><b>@</b><i>server</i>, where the username is <i>username</i>@<i>server</i>, where
<i>server</i> is the address of the SMTP server and <i>server</i> is the address of the SMTP server and
<i>username</i> is the user&acute;s login on this SMTP <i>username</i> is the user&acute;s login on this SMTP
server. The login itself may contain an &acute;@&acute; server. The login itself may contain an &acute;@&acute;
@ -229,8 +251,7 @@ https://3proxy.org/</p>
<p style="margin-left:6%; margin-top: 1em">3proxy is <p style="margin-left:6%; margin-top: 1em">3proxy is
designed by Vladimir 3APA3A Dubrovin designed by Vladimir Dubrovin &lt;vlad@3proxy.org&gt;</p>
(<i>3proxy@3proxy.org</i>)</p>
<hr> <hr>
</body> </body>
</html> </html>

View File

@ -57,11 +57,11 @@ connections and UDP portmapping.</p>
cellspacing="0" cellpadding="0"> cellspacing="0" cellpadding="0">
<tr valign="top" align="left"> <tr valign="top" align="left">
<td width="6%"></td> <td width="6%"></td>
<td width="4%"> <td width="3%">
<p style="margin-top: 1em"><b>-I</b></p></td> <p style="margin-top: 1em"><b>-I</b></p></td>
<td width="5%"></td> <td width="6%"></td>
<td width="85%"> <td width="85%">
@ -69,11 +69,11 @@ connections and UDP portmapping.</p>
only.</p> </td></tr> only.</p> </td></tr>
<tr valign="top" align="left"> <tr valign="top" align="left">
<td width="6%"></td> <td width="6%"></td>
<td width="4%"> <td width="3%">
<p style="margin-top: 1em"><b>-d</b></p></td> <p style="margin-top: 1em"><b>-d</b></p></td>
<td width="5%"></td> <td width="6%"></td>
<td width="85%"> <td width="85%">
@ -81,11 +81,11 @@ only.</p> </td></tr>
console and run in the background.</p></td></tr> console and run in the background.</p></td></tr>
<tr valign="top" align="left"> <tr valign="top" align="left">
<td width="6%"></td> <td width="6%"></td>
<td width="4%"> <td width="3%">
<p style="margin-top: 1em"><b>-t</b></p></td> <p style="margin-top: 1em"><b>-t</b></p></td>
<td width="5%"></td> <td width="6%"></td>
<td width="85%"> <td width="85%">
@ -93,11 +93,11 @@ console and run in the background.</p></td></tr>
start/stop/accept error records.</p></td></tr> start/stop/accept error records.</p></td></tr>
<tr valign="top" align="left"> <tr valign="top" align="left">
<td width="6%"></td> <td width="6%"></td>
<td width="4%"> <td width="3%">
<p style="margin-top: 1em"><b>-u</b></p></td> <p style="margin-top: 1em"><b>-u</b></p></td>
<td width="5%"></td> <td width="6%"></td>
<td width="85%"> <td width="85%">
@ -105,11 +105,11 @@ start/stop/accept error records.</p></td></tr>
authentication</p> </td></tr> authentication</p> </td></tr>
<tr valign="top" align="left"> <tr valign="top" align="left">
<td width="6%"></td> <td width="6%"></td>
<td width="4%"> <td width="3%">
<p style="margin-top: 1em"><b>-e</b></p></td> <p style="margin-top: 1em"><b>-e</b></p></td>
<td width="5%"></td> <td width="6%"></td>
<td width="85%"> <td width="85%">
@ -118,22 +118,44 @@ the interface the proxy should initiate connections from.
External IP must be specified if you need incoming External IP must be specified if you need incoming
connections. By default, the system will decide which connections. By default, the system will decide which
address to use in accordance with the routing table.</p></td></tr> 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"> <tr valign="top" align="left">
<td width="6%"></td> <td width="6%"></td>
<td width="4%"> <td width="4%">
<p style="margin-top: 1em"><b>-Ne</b></p></td> <p><b>-Ne</b></p></td>
<td width="5%"></td> <td width="5%"></td>
<td width="85%"> <td width="85%">
<p style="margin-top: 1em">External NAT address 3proxy <p>External NAT address 3proxy reports to client for
reports to client for CONNECT/BIND. This is external address CONNECT/BIND. This is external address of NAT between 3proxy
of NAT between 3proxy and destination server. By default, and destination server. By default, the external address is
the external address is reported. It&rsquo;s only useful in reported. It&rsquo;s only useful in the case of IP-IP NAT
the case of IP-IP NAT and does not work with port and does not work with port translation.</p></td></tr>
translation.</p> </td></tr>
<tr valign="top" align="left"> <tr valign="top" align="left">
<td width="6%"></td> <td width="6%"></td>
<td width="4%"> <td width="4%">
@ -247,8 +269,7 @@ https://3proxy.org/</p>
<p style="margin-left:6%; margin-top: 1em">3proxy is <p style="margin-left:6%; margin-top: 1em">3proxy is
designed by Vladimir 3APA3A Dubrovin designed by Vladimir Dubrovin &lt;vlad@3proxy.org&gt;</p>
(<i>3proxy@3proxy.org</i>)</p>
<hr> <hr>
</body> </body>
</html> </html>

View File

@ -104,23 +104,45 @@ start/stop/accept error records.</p></td></tr>
the interface the proxy should initiate connections from. By the interface the proxy should initiate connections from. By
default, the system will decide which address to use in default, the system will decide which address to use in
accordance with the routing table.</p></td></tr> 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"> <tr valign="top" align="left">
<td width="6%"></td> <td width="6%"></td>
<td width="3%"> <td width="3%">
<p style="margin-top: 1em"><b>-i</b></p></td> <p><b>-i</b></p></td>
<td width="6%"></td> <td width="6%"></td>
<td width="85%"> <td width="85%">
<p style="margin-top: 1em">Internal address. IP address the <p>Internal address. IP address the proxy accepts
proxy accepts connections to. By default, connections to any connections to. By default, connections to any interface are
interface are accepted. It&acute;s usually unsafe. Unix accepted. It&acute;s usually unsafe. Unix domain sockets can
domain sockets can be specified with be specified with <i>-iunix:/path/to/socket</i> syntax
<i>-iunix:/path/to/socket</i> syntax (e.g., (e.g., -iunix:/var/run/tcppm.sock). On Linux, abstract
-iunix:/var/run/tcppm.sock). On Linux, abstract sockets use sockets use <i>-iunix:@socketname</i> syntax.</p></td></tr>
<i>-iunix:@socketname</i> syntax.</p></td></tr>
<tr valign="top" align="left"> <tr valign="top" align="left">
<td width="6%"></td> <td width="6%"></td>
<td width="3%"> <td width="3%">
@ -212,8 +234,7 @@ https://3proxy.org/</p>
<p style="margin-left:6%; margin-top: 1em">3proxy is <p style="margin-left:6%; margin-top: 1em">3proxy is
designed by Vladimir 3APA3A Dubrovin designed by Vladimir Dubrovin &lt;vlad@3proxy.org&gt;</p>
(<i>3proxy@3proxy.org</i>)</p>
<hr> <hr>
</body> </body>
</html> </html>

View File

@ -60,11 +60,11 @@ plugin).</p>
cellspacing="0" cellpadding="0"> cellspacing="0" cellpadding="0">
<tr valign="top" align="left"> <tr valign="top" align="left">
<td width="6%"></td> <td width="6%"></td>
<td width="4%"> <td width="3%">
<p style="margin-top: 1em"><b>-I</b></p></td> <p style="margin-top: 1em"><b>-I</b></p></td>
<td width="5%"></td> <td width="6%"></td>
<td width="85%"> <td width="85%">
@ -72,11 +72,11 @@ plugin).</p>
only.</p> </td></tr> only.</p> </td></tr>
<tr valign="top" align="left"> <tr valign="top" align="left">
<td width="6%"></td> <td width="6%"></td>
<td width="4%"> <td width="3%">
<p style="margin-top: 1em"><b>-d</b></p></td> <p style="margin-top: 1em"><b>-d</b></p></td>
<td width="5%"></td> <td width="6%"></td>
<td width="85%"> <td width="85%">
@ -84,11 +84,11 @@ only.</p> </td></tr>
console and run in the background.</p></td></tr> console and run in the background.</p></td></tr>
<tr valign="top" align="left"> <tr valign="top" align="left">
<td width="6%"></td> <td width="6%"></td>
<td width="4%"> <td width="3%">
<p style="margin-top: 1em"><b>-t</b></p></td> <p style="margin-top: 1em"><b>-t</b></p></td>
<td width="5%"></td> <td width="6%"></td>
<td width="85%"> <td width="85%">
@ -96,11 +96,11 @@ console and run in the background.</p></td></tr>
start/stop/accept error records.</p></td></tr> start/stop/accept error records.</p></td></tr>
<tr valign="top" align="left"> <tr valign="top" align="left">
<td width="6%"></td> <td width="6%"></td>
<td width="4%"> <td width="3%">
<p style="margin-top: 1em"><b>-u</b></p></td> <p style="margin-top: 1em"><b>-u</b></p></td>
<td width="5%"></td> <td width="6%"></td>
<td width="85%"> <td width="85%">
@ -108,11 +108,11 @@ start/stop/accept error records.</p></td></tr>
authentication</p> </td></tr> authentication</p> </td></tr>
<tr valign="top" align="left"> <tr valign="top" align="left">
<td width="6%"></td> <td width="6%"></td>
<td width="4%"> <td width="3%">
<p style="margin-top: 1em"><b>-e</b></p></td> <p style="margin-top: 1em"><b>-e</b></p></td>
<td width="5%"></td> <td width="6%"></td>
<td width="85%"> <td width="85%">
@ -120,23 +120,45 @@ authentication</p> </td></tr>
the interface the proxy should initiate connections from. By the interface the proxy should initiate connections from. By
default, the system will decide which address to use in default, the system will decide which address to use in
accordance with the routing table.</p></td></tr> 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"> <tr valign="top" align="left">
<td width="6%"></td> <td width="6%"></td>
<td width="4%"> <td width="4%">
<p style="margin-top: 1em"><b>-i</b></p></td> <p><b>-i</b></p></td>
<td width="5%"></td> <td width="5%"></td>
<td width="85%"> <td width="85%">
<p style="margin-top: 1em">Internal address. IP address the <p>Internal address. IP address the proxy accepts
proxy accepts connections to. By default, connections to any connections to. By default, connections to any interface are
interface are accepted. It&acute;s usually unsafe. Unix accepted. It&acute;s usually unsafe. Unix domain sockets can
domain sockets can be specified with be specified with <i>-iunix:/path/to/socket</i> syntax
<i>-iunix:/path/to/socket</i> syntax (e.g., (e.g., -iunix:/var/run/tlspr.sock). On Linux, abstract
-iunix:/var/run/tlspr.sock). On Linux, abstract sockets use sockets use <i>-iunix:@socketname</i> syntax.</p></td></tr>
<i>-iunix:@socketname</i> syntax.</p></td></tr>
<tr valign="top" align="left"> <tr valign="top" align="left">
<td width="6%"></td> <td width="6%"></td>
<td width="4%"> <td width="4%">
@ -269,8 +291,7 @@ https://3proxy.org/</p>
<p style="margin-left:6%; margin-top: 1em">3proxy is <p style="margin-left:6%; margin-top: 1em">3proxy is
designed by Vladimir 3APA3A Dubrovin designed by Vladimir Dubrovin &lt;vlad@3proxy.org&gt;</p>
(<i>3proxy@3proxy.org</i>)</p>
<hr> <hr>
</body> </body>
</html> </html>

View File

@ -104,19 +104,42 @@ start/stop/accept error records.</p></td></tr>
the interface the proxy should initiate datagrams from. By the interface the proxy should initiate datagrams from. By
default, the system will decide which address to use in default, the system will decide which address to use in
accordance with the routing table.</p></td></tr> 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"> <tr valign="top" align="left">
<td width="6%"></td> <td width="6%"></td>
<td width="3%"> <td width="3%">
<p style="margin-top: 1em"><b>-i</b></p></td> <p><b>-i</b></p></td>
<td width="6%"></td> <td width="6%"></td>
<td width="85%"> <td width="85%">
<p style="margin-top: 1em">Internal address. IP address the <p>Internal address. IP address the proxy accepts datagrams
proxy accepts datagrams to. By default, connections to any to. By default, connections to any interface are accepted.
interface are accepted. It&acute;s usually unsafe.</p></td></tr> It&acute;s usually unsafe.</p></td></tr>
<tr valign="top" align="left"> <tr valign="top" align="left">
<td width="6%"></td> <td width="6%"></td>
<td width="3%"> <td width="3%">
@ -218,8 +241,7 @@ https://3proxy.org/</p>
<p style="margin-left:6%; margin-top: 1em">3proxy is <p style="margin-left:6%; margin-top: 1em">3proxy is
designed by Vladimir 3APA3A Dubrovin designed by Vladimir Dubrovin &lt;vlad@3proxy.org&gt;</p>
(<i>3proxy@3proxy.org</i>)</p>
<hr> <hr>
</body> </body>
</html> </html>

View File

@ -1,10 +1,13 @@
<h3>3proxy PCRE (Perl Compatible Regular Expressions) Filtering</h3>
<h3>3proxy Perl Compatible Regular Expressions (PCRE) Plugin</h3> <p><b>Note:</b> Since version 0.9.7, PCRE filtering is built into 3proxy and does not require
a separate plugin. All pcre_* commands are available directly when 3proxy is compiled with
PCRE2 support (WITH_PCRE). The plugin line is no longer needed.</p>
This filtering plugin can be used to create matching and replacement <p>This filtering functionality can be used to create matching and replacement
rules with regular expressions for client requests, client and rules with regular expressions for client requests, client and
server headers, and client and server data. It adds 3 additional server headers, and client and server data. It adds 3 additional
configuration commands: configuration commands:</p>
<pre> <pre>
pcre TYPE FILTER_ACTION REGEXP [ACE] pcre TYPE FILTER_ACTION REGEXP [ACE]
@ -78,16 +81,10 @@ authentication and/or allow/deny ACLs.
<h4>Example:</h4> <h4>Example:</h4>
<pre> <pre>
plugin PCREPlugin.dll pcre_plugin
pcre request deny "porn|sex" user1,user2,user3 192.168.0.0/16 pcre request deny "porn|sex" user1,user2,user3 192.168.0.0/16
pcre srvheader deny "Content-type: application" pcre srvheader deny "Content-type: application"
pcre_rewrite clidata,srvdata dunno "porn|sex|pussy" "***" baduser pcre_rewrite clidata,srvdata dunno "porn|sex|pussy" "***" baduser
pcre_extend deny * 192.168.0.1/16 pcre_extend deny * 192.168.0.1/16
</pre> </pre>
<h4>Download:</h4> &copy; Vladimir Dubrovin, License: BSD style
<ul>
<li>Plugin is included in the 3proxy 0.6 binary and source distribution
<li>Example configuration (by Dennis Garber): <A HREF="NoPornLitest.cfg.txt">NoPornLitest.cfg</A>
</li></ul>

View File

@ -1,8 +1,12 @@
<h3>Плагин регулярных выражений совместимых с Perl (PCRE) для 3proxy</h3> <h3>Фильтрация PCRE (Perl Compatible Regular Expressions) в 3proxy</h3>
Фильтрующий плагин используется для создания правил поиска и замены <p><b>Примечание:</b> Начиная с версии 0.9.7 фильтрация PCRE встроена в 3proxy и не требует
отдельного плагина. Все команды pcre_* доступны напрямую при компиляции 3proxy с поддержкой
PCRE2 (WITH_PCRE). Строка plugin больше не нужна.</p>
<p>Фильтрующий плагин используется для создания правил поиска и замены
регулярных выражений в запросе, заголовков запроса и ответа и данных. регулярных выражений в запросе, заголовков запроса и ответа и данных.
Добавляет поддержку 3х новых команд в файле конфигурации: Добавляет поддержку 3х новых команд в файле конфигурации:</p>
<pre> <pre>
pcre TYPE FILTER_ACTION REGEXP [ACE] pcre TYPE FILTER_ACTION REGEXP [ACE]
@ -76,15 +80,10 @@ PCRE_BSR_UNICODE
<h4>Пример:</h4> <h4>Пример:</h4>
<pre> <pre>
plugin PCREPlugin.dll pcre_plugin
pcre request deny "porn|sex" user1,user2,user3 192.168.0.0/16 pcre request deny "porn|sex" user1,user2,user3 192.168.0.0/16
pcre srvheader deny "Content-type: application" pcre srvheader deny "Content-type: application"
pcre_rewrite clidata,srvdata dunno "porn|sex|pussy" "***" baduser pcre_rewrite clidata,srvdata dunno "porn|sex|pussy" "***" baduser
pcre_extend deny * 192.168.0.1/16 pcre_extend deny * 192.168.0.1/16
</pre> </pre>
<h4>Загрузить:</h4> &copy; Vladimir Dubrovin, License: BSD style
<ul>
<li>Плагин включен в дистрибутив 3proxy 0.6
<li>Пример конфигурации (by Dennis Garber): <A HREF="NoPornLitest.cfg.txt">NoPornLitest.cfg</A>
</li></ul>

View File

@ -1,6 +1,11 @@
<h3>3proxy SSL/TLS Plugin</h3> <h3>3proxy SSL/TLS Support</h3>
This plugin can be used to transparently decrypt SSL/TLS data, provide TLS encryption for proxy traffic, and authenticate using client certificates. <p><b>Note:</b> Since version 0.9.7, SSL/TLS support is built into 3proxy and does not require
a separate plugin. All ssl_* commands are available directly when 3proxy is compiled with
OpenSSL support (WITH_SSL). The plugin line is no longer needed.</p>
<p>SSL/TLS support can be used to transparently decrypt SSL/TLS data, provide TLS encryption
for proxy traffic, and authenticate using client certificates.</p>
<h4>For transparent certificate spoofing (MITM):</h4> <h4>For transparent certificate spoofing (MITM):</h4>
@ -55,7 +60,6 @@ Generated certificates are placed in the same path.
<h4>MITM example:</h4> <h4>MITM example:</h4>
<pre> <pre>
plugin /path/to/SSLPlugin.so ssl_plugin
ssl_server_ca_file /path/to/cafile ssl_server_ca_file /path/to/cafile
ssl_server_ca_key /path/to/cakey ssl_server_ca_key /path/to/cakey
ssl_mitm ssl_mitm
@ -67,7 +71,6 @@ MITM's traffic with a spoofed certificate for the port 3128 proxy.
<h4>https:// proxy example:</h4> <h4>https:// proxy example:</h4>
<pre> <pre>
plugin /path/to/SSLPlugin.so ssl_plugin
ssl_server_cert path_to_cert ssl_server_cert path_to_cert
ssl_server_key path_to_key ssl_server_key path_to_key
ssl_serv ssl_serv
@ -79,7 +82,6 @@ Creates an https:// proxy on port 33128 and an http:// proxy on port 3128
<h4>TLS client example (connect to upstream via TLS):</h4> <h4>TLS client example (connect to upstream via TLS):</h4>
<pre> <pre>
plugin /path/to/SSLPlugin.so ssl_plugin
ssl_client_cert /path/to/client.crt ssl_client_cert /path/to/client.crt
ssl_client_key /path/to/client.key ssl_client_key /path/to/client.key
ssl_client_verify ssl_client_verify
@ -91,7 +93,6 @@ Creates an HTTP proxy that connects to upstream servers via TLS with client cert
<h4>Conditional TLS for parent proxy (ssl_client_mode 3):</h4> <h4>Conditional TLS for parent proxy (ssl_client_mode 3):</h4>
<pre> <pre>
plugin /path/to/SSLPlugin.so ssl_plugin
ssl_server_cert /path/to/server.crt ssl_server_cert /path/to/server.crt
ssl_server_key /path/to/key ssl_server_key /path/to/key
ssl_client_mode 3 ssl_client_mode 3
@ -111,7 +112,6 @@ Creates an HTTP proxy on port 3128 that uses TLS for client connections (ssl_ser
<h4>mTLS example (require client certificate):</h4> <h4>mTLS example (require client certificate):</h4>
<pre> <pre>
plugin /path/to/SSLPlugin.so ssl_plugin
ssl_server_cert /path/to/server.crt ssl_server_cert /path/to/server.crt
ssl_server_key /path/to/server.key ssl_server_key /path/to/server.key
ssl_server_ca_file /path/to/ca.crt ssl_server_ca_file /path/to/ca.crt

View File

@ -1,6 +1,10 @@
<h3>3proxy SSL/TLS плагин</h3> <h3>3proxy SSL/TLS поддержка</h3>
Плагин можно использовать для перехвата и дешифровки SSL/TLS трафика, для шифрования трафика прокси-сервера и аутентификации с помощью клиентских сертификатов. <p><b>Примечание:</b> Начиная с версии 0.9.7 поддержка SSL/TLS встроена в 3proxy и не требует
отдельного плагина. Все команды ssl_* доступны напрямую при компиляции 3proxy с поддержкой
OpenSSL (WITH_SSL). Строка plugin больше не нужна.</p>
<p>Плагин можно использовать для перехвата и дешифровки SSL/TLS трафика, для шифрования трафика прокси-сервера и аутентификации с помощью клиентских сертификатов.</p>
<h4>Для прозрачного перехвата трафика (MITM):</h4> <h4>Для прозрачного перехвата трафика (MITM):</h4>
@ -52,7 +56,6 @@ ssl_server_ca_key и ssl_server_key соответственно, если он
<h4>Пример MITM:</h4> <h4>Пример MITM:</h4>
<pre> <pre>
plugin /path/to/SSLPlugin.so ssl_plugin
ssl_server_ca_file /path/to/cafile ssl_server_ca_file /path/to/cafile
ssl_server_ca_key /path/to/cakey ssl_server_ca_key /path/to/cakey
ssl_mitm ssl_mitm
@ -64,7 +67,6 @@ proxy -p3129
<h4>Пример конфигурации https:// прокси:</h4> <h4>Пример конфигурации https:// прокси:</h4>
<pre> <pre>
plugin /path/to/SSLPlugin.so ssl_plugin
ssl_server_cert path_to_cert ssl_server_cert path_to_cert
ssl_server_key path_to_key ssl_server_key path_to_key
ssl_serv ssl_serv
@ -76,7 +78,6 @@ proxy -p3128
<h4>Пример TLS-клиента (соединение к вышестоящему серверу через TLS):</h4> <h4>Пример TLS-клиента (соединение к вышестоящему серверу через TLS):</h4>
<pre> <pre>
plugin /path/to/SSLPlugin.so ssl_plugin
ssl_client_cert /path/to/client.crt ssl_client_cert /path/to/client.crt
ssl_client_key /path/to/client.key ssl_client_key /path/to/client.key
ssl_client_verify ssl_client_verify
@ -88,7 +89,6 @@ proxy -p3128
<h4>Условное TLS для parent прокси (ssl_client_mode 3):</h4> <h4>Условное TLS для parent прокси (ssl_client_mode 3):</h4>
<pre> <pre>
plugin /path/to/SSLPlugin.so ssl_plugin
ssl_server_cert /path/to/server.crt ssl_server_cert /path/to/server.crt
ssl_server_key /path/to/key ssl_server_key /path/to/key
ssl_client_mode 3 ssl_client_mode 3
@ -108,7 +108,6 @@ ssl_nocli
<h4>Пример mTLS (требование клиентского сертификата):</h4> <h4>Пример mTLS (требование клиентского сертификата):</h4>
<pre> <pre>
plugin /path/to/SSLPlugin.so ssl_plugin
ssl_server_cert /path/to/server.crt ssl_server_cert /path/to/server.crt
ssl_server_key /path/to/server.key ssl_server_key /path/to/server.key
ssl_server_ca_file /path/to/ca.crt ssl_server_ca_file /path/to/ca.crt

View File

@ -1,4 +1,4 @@
.TH 3proxy "8" "January 2019" "3proxy 0.9" "Universal proxy server" .TH 3proxy "8" "May 2026" "3proxy 0.9" "Universal proxy server"
.SH NAME .SH NAME
.B 3proxy .B 3proxy
\- 3[APA3A] tiny proxy server, or trivial proxy server, or free proxy \- 3[APA3A] tiny proxy server, or trivial proxy server, or free proxy
@ -140,12 +140,9 @@ configuration file
Report all bugs to Report all bugs to
.BR 3proxy@3proxy.org .BR 3proxy@3proxy.org
.SH SEE ALSO .SH SEE ALSO
3proxy.cfg(3), proxy(8), ftppr(8), socks(8), pop3p(8), tcppm(8), udppm(8), 3proxy.cfg(5), proxy(8), ftppr(8), socks(8), pop3p(8), tcppm(8), udppm(8),
kill(1), syslogd(8), kill(1), syslogd(8),
.br .br
https://3proxy.org/ https://3proxy.org/
.SH TRIVIA
3APA3A is pronounced as \`\`zaraza\'\'.
.SH AUTHORS .SH AUTHORS
3proxy is designed by Vladimir 3APA3A Dubrovin 3proxy is designed by Vladimir Dubrovin <vlad@3proxy.org>
.RI ( 3proxy@3proxy.org )

File diff suppressed because it is too large Load Diff

80
man/3proxy_crypt.8 Normal file
View File

@ -0,0 +1,80 @@
.TH 3proxy_crypt "8" "May 2026" "3proxy 0.9" "Universal proxy server"
.SH NAME
.B 3proxy_crypt
\- utility to generate encrypted passwords for 3proxy
.SH SYNOPSIS
.B 3proxy_crypt
.I password
.br
.B 3proxy_crypt
.I salt password
.SH DESCRIPTION
.B 3proxy_crypt
is a utility to generate encrypted password hashes for use with 3proxy
configuration. Encrypted passwords allow the system to avoid storing
passwords in cleartext in configuration files.
.PP
When invoked with a single argument, it produces an NT password hash
(MD4-based, suitable for NTLM authentication). The output is prefixed with
.BR NT: .
.PP
When invoked with two arguments (salt and password), it produces a BLAKE2b
password hash. The salt length is limited to 64 characters. The output is
prefixed with
.BR CR: .
.PP
The resulting hash can be used in the 3proxy configuration file with the
.B users
directive instead of a cleartext password.
.SH OPTIONS
.TP
.I password
Cleartext password to encrypt.
.TP
.I salt
Salt string for BLAKE2b hashing (max 64 characters).
.SH EXAMPLE
.TP
Generate NT password hash:
.RS
3proxy_crypt MySecretPassword
.RE
.TP
Result:
.RS
NT:3F7E6D8D96E8E7A9B0C1D2E3F4A5B6C7
.RE
.TP
Generate BLAKE2b password hash with salt:
.RS
3proxy_crypt MySalt MySecretPassword
.RE
.TP
Result:
.RS
CR:$3$MySalt$...
.RE
.TP
Using in 3proxy.cfg:
.RS
users user1:CR:$3$MySalt$...
.RE
.SH NOTES
The NT hash uses the RSA MD4 Message-Digest Algorithm. The BLAKE2b hash
uses the BLAKE2 cryptographic hash function.
.PP
When a password hash is prefixed with
.B NT:
or
.BR CR: ,
3proxy uses the corresponding algorithm to verify passwords instead of
comparing cleartext strings.
.SH BUGS
Report all bugs to
.BR 3proxy@3proxy.org
.SH SEE ALSO
3proxy(8), 3proxy.cfg(5),
.br
https://3proxy.org/
.SH AUTHORS
3proxy is designed by Vladimir Dubrovin <vlad@3proxy.org>

View File

@ -1,4 +1,4 @@
.TH ftppr "8" "January 2019" "3proxy 0.9" "Universal proxy server" .TH ftppr "8" "May 2026" "3proxy 0.9" "Universal proxy server"
.SH NAME .SH NAME
.B ftppr .B ftppr
\- FTP proxy gateway service \- FTP proxy gateway service
@ -33,6 +33,24 @@ from.
By default, the system will decide which address to use in accordance By default, the system will decide which address to use in accordance
with the routing table. with the routing table.
.TP .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 .B -i
Internal address. IP address the proxy accepts connections to. Internal address. IP address the proxy accepts connections to.
By default, connections to any interface are accepted. It\'s usually unsafe. By default, connections to any interface are accepted. It\'s usually unsafe.
@ -73,7 +91,7 @@ and
.IR port .IR port
as the FTP server. The address of the real FTP server must be configured as a part of as the FTP server. The address of the real FTP server must be configured as a part of
the FTP username. The format for the username is the FTP username. The format for the username is
.IR username \fB@ server , .IR username @ server ,
where where
.I server .I server
is the address of the FTP server and is the address of the FTP server and
@ -88,5 +106,4 @@ Report all bugs to
.br .br
https://3proxy.org/ https://3proxy.org/
.SH AUTHORS .SH AUTHORS
3proxy is designed by Vladimir 3APA3A Dubrovin 3proxy is designed by Vladimir Dubrovin <vlad@3proxy.org>
.RI ( 3proxy@3proxy.org )

View File

@ -1,4 +1,4 @@
.TH pop3p "8" "January 2019" "3proxy 0.9" "Universal proxy server" .TH pop3p "8" "May 2026" "3proxy 0.9" "Universal proxy server"
.SH NAME .SH NAME
.B pop3p .B pop3p
\- POP3 proxy gateway service \- POP3 proxy gateway service
@ -33,6 +33,24 @@ from.
By default, the system will decide which address to use in accordance By default, the system will decide which address to use in accordance
with the routing table. with the routing table.
.TP .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 .B -i
Internal address. IP address the proxy accepts connections to. Internal address. IP address the proxy accepts connections to.
By default, connections to any interface are accepted. It\'s usually unsafe. By default, connections to any interface are accepted. It\'s usually unsafe.
@ -67,7 +85,7 @@ and
.IR port .IR port
as a POP3 server. The address of the real POP3 server must be configured as a part of as a POP3 server. The address of the real POP3 server must be configured as a part of
the POP3 username. The format for the username is the POP3 username. The format for the username is
.IR username \fB@ server , .IR username @ server ,
where where
.I server .I server
is the address of the POP3 server and is the address of the POP3 server and
@ -84,5 +102,4 @@ Report all bugs to
.br .br
https://3proxy.org/ https://3proxy.org/
.SH AUTHORS .SH AUTHORS
3proxy is designed by Vladimir 3APA3A Dubrovin 3proxy is designed by Vladimir Dubrovin <vlad@3proxy.org>
.RI ( 3proxy@3proxy.org )

View File

@ -1,4 +1,4 @@
.TH proxy "8" "January 2019" "3proxy 0.9" "Universal proxy server" .TH proxy "8" "May 2026" "3proxy 0.9" "Universal proxy server"
.SH NAME .SH NAME
.B proxy .B proxy
\- HTTP proxy gateway service \- HTTP proxy gateway service
@ -31,6 +31,24 @@ from.
By default, the system will decide which address to use in accordance By default, the system will decide which address to use in accordance
with the routing table. with the routing table.
.TP .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 .B -i
Internal address. IP address the proxy accepts connections to. Internal address. IP address the proxy accepts connections to.
By default, connections to any interface are accepted. It\'s usually unsafe. By default, connections to any interface are accepted. It\'s usually unsafe.
@ -79,5 +97,4 @@ Report all bugs to
.br .br
https://3proxy.org/ https://3proxy.org/
.SH AUTHORS .SH AUTHORS
3proxy is designed by Vladimir 3APA3A Dubrovin 3proxy is designed by Vladimir Dubrovin <vlad@3proxy.org>
.RI ( 3proxy@3proxy.org )

View File

@ -1,4 +1,4 @@
.TH smtpp "8" "January 2019" "3proxy 0.9" "Universal proxy server" .TH smtpp "8" "May 2026" "3proxy 0.9" "Universal proxy server"
.SH NAME .SH NAME
.B smtpp .B smtpp
\- SMTP proxy gateway service \- SMTP proxy gateway service
@ -33,6 +33,24 @@ from.
By default, the system will decide which address to use in accordance By default, the system will decide which address to use in accordance
with the routing table. with the routing table.
.TP .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 .B -i
Internal address. IP address the proxy accepts connections to. Internal address. IP address the proxy accepts connections to.
By default, connections to any interface are accepted. It\'s usually unsafe. By default, connections to any interface are accepted. It\'s usually unsafe.
@ -68,7 +86,7 @@ and
.IR port .IR port
as an SMTP server. The address of the real SMTP server must be configured as a part of as an SMTP server. The address of the real SMTP server must be configured as a part of
the SMTP username. The format for the username is the SMTP username. The format for the username is
.IR username \fB@ server , .IR username @ server ,
where where
.I server .I server
is the address of the SMTP server and is the address of the SMTP server and
@ -85,5 +103,4 @@ Report all bugs to
.br .br
https://3proxy.org/ https://3proxy.org/
.SH AUTHORS .SH AUTHORS
3proxy is designed by Vladimir 3APA3A Dubrovin 3proxy is designed by Vladimir Dubrovin <vlad@3proxy.org>
.RI ( 3proxy@3proxy.org )

View File

@ -1,4 +1,4 @@
.TH socks "8" "January 2019" "3proxy 0.9" "Universal proxy server" .TH socks "8" "May 2026" "3proxy 0.9" "Universal proxy server"
.SH NAME .SH NAME
.B socks .B socks
\- SOCKS 4/4.5/5 gateway service \- SOCKS 4/4.5/5 gateway service
@ -33,6 +33,24 @@ from. External IP must be specified if you need incoming connections.
By default, the system will decide which address to use in accordance By default, the system will decide which address to use in accordance
with the routing table. with the routing table.
.TP .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 -Ne .B -Ne
External NAT address 3proxy reports to client for CONNECT/BIND. External NAT address 3proxy reports to client for CONNECT/BIND.
This is external address of NAT between 3proxy and destination server. This is external address of NAT between 3proxy and destination server.
@ -93,5 +111,4 @@ Report all bugs to
.br .br
https://3proxy.org/ https://3proxy.org/
.SH AUTHORS .SH AUTHORS
3proxy is designed by Vladimir 3APA3A Dubrovin 3proxy is designed by Vladimir Dubrovin <vlad@3proxy.org>
.RI ( 3proxy@3proxy.org )

View File

@ -1,4 +1,4 @@
.TH tcppm "8" "January 2019" "3proxy 0.9" "Universal proxy server" .TH tcppm "8" "May 2026" "3proxy 0.9" "Universal proxy server"
.SH NAME .SH NAME
.B tcppm .B tcppm
\- TCP port mapper \- TCP port mapper
@ -28,6 +28,24 @@ from.
By default, the system will decide which address to use in accordance By default, the system will decide which address to use in accordance
with the routing table. with the routing table.
.TP .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 .B -i
Internal address. IP address the proxy accepts connections to. Internal address. IP address the proxy accepts connections to.
By default, connections to any interface are accepted. It\'s usually unsafe. By default, connections to any interface are accepted. It\'s usually unsafe.
@ -82,5 +100,4 @@ Report all bugs to
.br .br
https://3proxy.org/ https://3proxy.org/
.SH AUTHORS .SH AUTHORS
3proxy is designed by Vladimir 3APA3A Dubrovin 3proxy is designed by Vladimir Dubrovin <vlad@3proxy.org>
.RI ( 3proxy@3proxy.org )

View File

@ -1,4 +1,4 @@
.TH tlspr "8" "May 2024" "3proxy 0.9" "Universal proxy server" .TH tlspr "8" "May 2026" "3proxy 0.9" "Universal proxy server"
.SH NAME .SH NAME
.B tlspr .B tlspr
\- SNI proxy gateway service \- SNI proxy gateway service
@ -33,6 +33,24 @@ from.
By default, the system will decide which address to use in accordance By default, the system will decide which address to use in accordance
with the routing table. with the routing table.
.TP .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 .B -i
Internal address. IP address the proxy accepts connections to. Internal address. IP address the proxy accepts connections to.
By default, connections to any interface are accepted. It\'s usually unsafe. By default, connections to any interface are accepted. It\'s usually unsafe.
@ -86,5 +104,4 @@ Report all bugs to
.br .br
https://3proxy.org/ https://3proxy.org/
.SH AUTHORS .SH AUTHORS
3proxy is designed by Vladimir 3APA3A Dubrovin 3proxy is designed by Vladimir Dubrovin <vlad@3proxy.org>
.RI ( 3proxy@3proxy.org )

View File

@ -1,4 +1,4 @@
.TH udppm "8" "January 2019" "3proxy 0.9" "Universal proxy server" .TH udppm "8" "May 2026" "3proxy 0.9" "Universal proxy server"
.SH NAME .SH NAME
.B udppm .B udppm
\- UDP port mapper \- UDP port mapper
@ -28,6 +28,24 @@ from.
By default, the system will decide which address to use in accordance By default, the system will decide which address to use in accordance
with the routing table. with the routing table.
.TP .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 .B -i
Internal address. IP address the proxy accepts datagrams to. Internal address. IP address the proxy accepts datagrams to.
By default, connections to any interface are accepted. It\'s usually unsafe. By default, connections to any interface are accepted. It\'s usually unsafe.
@ -75,5 +93,4 @@ Report all bugs to
.br .br
https://3proxy.org/ https://3proxy.org/
.SH AUTHORS .SH AUTHORS
3proxy is designed by Vladimir 3APA3A Dubrovin 3proxy is designed by Vladimir Dubrovin <vlad@3proxy.org>
.RI ( 3proxy@3proxy.org )

View File

@ -32,14 +32,15 @@ make clean
%files %files
/bin/3proxy /bin/3proxy
/bin/ftppr
/bin/3proxy_crypt /bin/3proxy_crypt
/bin/pop3p /bin/3proxy_ftppr
/bin/proxy /bin/3proxy_pop3p
/bin/socks /bin/3proxy_proxy
/bin/tcppm /bin/3proxy_smtpp
/bin/udppm /bin/3proxy_socks
/bin/tlspr /bin/3proxy_tcppm
/bin/3proxy_tlspr
/bin/3proxy_udppm
%config(noreplace) /etc/3proxy/3proxy.cfg %config(noreplace) /etc/3proxy/3proxy.cfg
/etc/3proxy/conf /etc/3proxy/conf
/etc/init.d/3proxy /etc/init.d/3proxy
@ -49,7 +50,7 @@ make clean
%config(noreplace) /usr/local/3proxy/conf/bandlimiters %config(noreplace) /usr/local/3proxy/conf/bandlimiters
%config(noreplace) /usr/local/3proxy/conf/counters %config(noreplace) /usr/local/3proxy/conf/counters
/usr/local/3proxy/libexec/*.ld.so /usr/local/3proxy/libexec/*.ld.so
/usr/share/man/man3/* /usr/share/man/man5/3proxy.cfg.5
/usr/share/man/man8/* /usr/share/man/man8/*
/var/log/3proxy /var/log/3proxy

View File

@ -1,12 +1,18 @@
/* /*
3APA3A simplest proxy server 3APA3A simplest proxy server
(c) 2002-2021 by Vladimir Dubrovin <3proxy@3proxy.org> (c) 2002-2026 by Vladimir Dubrovin <vlad@3proxy.org>
please read License Agreement please read License Agreement
*/ */
#include "proxy.h" #include "proxy.h"
#ifdef WITH_SSL
void ssl_install(void);
#endif
#ifdef WITH_PCRE
void pcre_install(void);
#endif
#ifndef _WIN32 #ifndef _WIN32
#include <sys/resource.h> #include <sys/resource.h>
#ifndef NOPLUGINS #ifndef NOPLUGINS
@ -65,10 +71,10 @@ void __stdcall CommandHandler( DWORD dwCommand )
conf.paused++; conf.paused++;
Sleep(2000); Sleep(2000);
SetStatus( SERVICE_STOPPED, 0, 0 ); SetStatus( SERVICE_STOPPED, 0, 0 );
#ifndef NOODBC #ifdef WITH_ODBC
pthread_mutex_lock(&log_mutex); _3proxy_mutex_lock(&log_mutex);
close_sql(); close_sql();
pthread_mutex_unlock(&log_mutex); _3proxy_mutex_unlock(&log_mutex);
#endif #endif
break; break;
case SERVICE_CONTROL_PAUSE: case SERVICE_CONTROL_PAUSE:
@ -118,13 +124,6 @@ void mysigpause (int sig){
void mysigterm (int sig){ void mysigterm (int sig){
conf.paused++; conf.paused++;
usleep(999*SLEEPTIME);
usleep(999*SLEEPTIME);
#ifndef NOODBC
pthread_mutex_lock(&log_mutex);
close_sql();
pthread_mutex_unlock(&log_mutex);
#endif
conf.timetoexit = 1; conf.timetoexit = 1;
} }
@ -141,8 +140,10 @@ int timechanged (time_t oldtime, time_t newtime, ROTATION lt){
struct tm tmold; struct tm tmold;
struct tm *tm; struct tm *tm;
tm = localtime(&oldtime); tm = localtime(&oldtime);
if(!tm) return 0;
tmold = *tm; tmold = *tm;
tm = localtime(&newtime); tm = localtime(&newtime);
if(!tm) return 0;
switch(lt){ switch(lt){
case MINUTELY: case MINUTELY:
if(tm->tm_min != tmold.tm_min)return 1; if(tm->tm_min != tmold.tm_min)return 1;
@ -214,17 +215,17 @@ void dumpcounters(struct trafcount *tlin, int counterd){
cheader.updated = conf.time; cheader.updated = conf.time;
lseek(counterd, 0, SEEK_SET); if(lseek(counterd, 0, SEEK_SET) >= 0 && write(counterd, &cheader, sizeof(struct counter_header))){}
if(write(counterd, &cheader, sizeof(struct counter_header))){}
for(tl=tlin; tl; tl = tl->next){ for(tl=tlin; tl; tl = tl->next){
if(tl->number){ if(tl->number){
lseek(counterd, if(lseek(counterd,
sizeof(struct counter_header) + (tl->number - 1) * sizeof(struct counter_record), sizeof(struct counter_header) + (tl->number - 1) * sizeof(struct counter_record),
SEEK_SET); SEEK_SET) >= 0){
crecord.traf64 = tl->traf64; crecord.traf64 = tl->traf64;
crecord.cleared = tl->cleared; crecord.cleared = tl->cleared;
crecord.updated = tl->updated; crecord.updated = tl->updated;
if(write(counterd, &crecord, sizeof(struct counter_record))){} if(write(counterd, &crecord, sizeof(struct counter_record))){}
}
} }
if(tl->type!=NEVER && timechanged(tl->cleared, conf.time, tl->type)){ if(tl->type!=NEVER && timechanged(tl->cleared, conf.time, tl->type)){
tl->cleared = conf.time; tl->cleared = conf.time;
@ -267,9 +268,11 @@ void cyclestep(void){
} }
if(timechanged(basetime, conf.time, DAILY)) { if(timechanged(basetime, conf.time, DAILY)) {
tm = localtime(&conf.time); tm = localtime(&conf.time);
wday = (1 << tm->tm_wday); if(tm){
tm->tm_hour = tm->tm_min = tm->tm_sec = 0; wday = (1 << tm->tm_wday);
basetime = mktime(tm); tm->tm_hour = tm->tm_min = tm->tm_sec = 0;
basetime = mktime(tm);
}
} }
if(conf.logname) { if(conf.logname) {
if(timechanged(conf.logtime, conf.time, conf.logtype)) { if(timechanged(conf.logtime, conf.time, conf.logtype)) {
@ -486,7 +489,7 @@ int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int
} }
#endif #endif
#endif #endif
conf.conffile = mystrdup((argc==2)?argv[1]:(char*)DEFAULTCONFIG); conf.conffile = strdup((argc==2)?argv[1]:(char*)DEFAULTCONFIG);
if(conf.conffile && *conf.conffile != '-') { if(conf.conffile && *conf.conffile != '-') {
fp = confopen(); fp = confopen();
#ifndef _WIN32 #ifndef _WIN32
@ -508,31 +511,37 @@ int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int
return 1; return 1;
} }
pthread_mutex_init(&config_mutex, NULL); _3proxy_mutex_init(&config_mutex);
pthread_mutex_init(&bandlim_mutex, NULL); _3proxy_mutex_init(&bandlim_mutex);
pthread_mutex_init(&connlim_mutex, NULL); _3proxy_mutex_init(&connlim_mutex);
pthread_mutex_init(&hash_mutex, NULL); _3proxy_mutex_init(&tc_mutex);
pthread_mutex_init(&tc_mutex, NULL); _3proxy_mutex_init(&log_mutex);
pthread_mutex_init(&pwl_mutex, NULL);
pthread_mutex_init(&log_mutex, NULL);
#ifndef NORADIUS #ifndef NORADIUS
pthread_mutex_init(&rad_mutex, NULL); _3proxy_mutex_init(&rad_mutex);
#endif #endif
#ifdef _WIN32 #ifdef _WIN32
if(!CreatePipe(&conf.threadinit[0], &conf.threadinit[1], NULL, 1)){ conf.threadinit = CreateSemaphore(NULL, 1, 1, NULL);
#else if(!conf.threadinit){
if(pipe(conf.threadinit)) { fprintf(stderr, "semaphore init failed\n");
#endif
fprintf(stderr, "CreatePipe failed\n");
return 1; return 1;
}; }
#else
_3proxy_mutex_init(&conf.threadinit);
#endif
#ifdef WITH_SSL
ssl_install();
#endif
#ifdef WITH_PCRE
pcre_install();
#endif
freeconf(&conf); freeconf(&conf);
res = readconfig(fp); res = readconfig(fp);
conf.version++; conf.version++;
if(res) RETURN(res); if(res) RETURN(res);
if(!writable)fclose(fp); if(!writable){fclose(fp); fp = NULL;}
#ifdef _WIN32 #ifdef _WIN32
@ -563,6 +572,7 @@ int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int
CLEARRETURN: CLEARRETURN:
if(fp && fp != stdin) {fclose(fp); fp = NULL;}
return 0; return 0;
} }

View File

@ -1,15 +1,18 @@
/* /*
3APA3A simplest proxy server 3APA3A simplest proxy server
(c) 2002-2021 by Vladimir Dubrovin <3proxy@3proxy.org> (c) 2002-2026 by Vladimir Dubrovin <vlad@3proxy.org>
please read License Agreement please read License Agreement
*/ */
#ifndef WITHMAIN
#include "libs/md5.h"
#endif
#include "libs/md4.h"
#include "libs/blake2.h" #include "libs/blake2.h"
#ifdef WITH_SSL
#include <openssl/evp.h>
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
#include <openssl/params.h>
#include <openssl/core_names.h>
#endif
#endif
#include <string.h> #include <string.h>
#define MD5_SIZE 16 #define MD5_SIZE 16
@ -24,6 +27,12 @@ void tohex(unsigned char *in, unsigned char *out, int len);
static unsigned char itoa64[] = static unsigned char itoa64[] =
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
#if defined(WITH_SSL) && OPENSSL_VERSION_NUMBER >= 0x30000000L
EVP_MD *md4_hash = NULL;
EVP_MD *md5_hash = NULL;
#endif
void void
_crypt_to64(unsigned char *s, unsigned long v, int n) _crypt_to64(unsigned char *s, unsigned long v, int n)
{ {
@ -34,13 +43,22 @@ _crypt_to64(unsigned char *s, unsigned long v, int n)
} }
#ifdef WITH_SSL
unsigned char * ntpwdhash (unsigned char *szHash, const unsigned char *szPassword, int ctohex) unsigned char * ntpwdhash (unsigned char *szHash, const unsigned char *szPassword, int ctohex)
{ {
unsigned char szUnicodePass[513]; unsigned char szUnicodePass[513];
unsigned int nPasswordLen; unsigned int nPasswordLen;
MD4_CTX ctx; EVP_MD_CTX *ctx;
unsigned int len=sizeof(szUnicodePass);
unsigned int i; unsigned int i;
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
const EVP_MD *md4 = md4_hash;
#else
const EVP_MD *md4 = EVP_md4();
#endif
if(md4 == NULL) return NULL;
/* /*
* NT passwords are unicode. Convert plain text password * NT passwords are unicode. Convert plain text password
* to unicode by inserting a zero every other byte * to unicode by inserting a zero every other byte
@ -53,15 +71,23 @@ unsigned char * ntpwdhash (unsigned char *szHash, const unsigned char *szPasswor
} }
/* Encrypt Unicode password to a 16-byte MD4 hash */ /* Encrypt Unicode password to a 16-byte MD4 hash */
MD4Init(&ctx); ctx = EVP_MD_CTX_new();
MD4Update(&ctx, szUnicodePass, (nPasswordLen<<1)); if(!ctx) return NULL;
MD4Final(szUnicodePass, &ctx); if(!EVP_DigestInit_ex(ctx, md4, NULL)){
EVP_MD_CTX_free(ctx);
return NULL;
}
EVP_DigestUpdate(ctx, szUnicodePass, (nPasswordLen<<1));
EVP_DigestFinal_ex(ctx, szUnicodePass, &len);
EVP_MD_CTX_free(ctx);
if (ctohex){ if (ctohex){
tohex(szUnicodePass, szHash, 16); tohex(szUnicodePass, szHash, 16);
} }
else memcpy(szHash, szUnicodePass, 16); else memcpy(szHash, szUnicodePass, 16);
memset(szUnicodePass, 0, sizeof szUnicodePass);
return szHash; return szHash;
} }
#endif
unsigned char * mycrypt(const unsigned char *pw, const unsigned char *salt, unsigned char *passwd){ unsigned char * mycrypt(const unsigned char *pw, const unsigned char *salt, unsigned char *passwd){
@ -70,38 +96,61 @@ unsigned char * mycrypt(const unsigned char *pw, const unsigned char *salt, unsi
unsigned char *magic; unsigned char *magic;
unsigned char *p; unsigned char *p;
const unsigned char *sp; const unsigned char *sp;
unsigned char final[MD5_SIZE]; unsigned char final[MD5_SIZE] = {0};
int sl; int sl;
unsigned long l; unsigned long l;
#if defined(WITH_SSL)
#ifndef WITHMAIN #ifndef WITHMAIN
if(salt[0] == '$' && salt[1] == '1' && salt[2] == '$' && (ep = (unsigned char *)strchr((char *)salt+3, '$'))) { if(salt[0] == '$' && salt[1] == '1' && salt[2] == '$' && (ep = (unsigned char *)strchr((char *)salt+3, '$'))) {
MD5_CTX ctx,ctx1; EVP_MD_CTX *ctx, *ctx1;
unsigned int len;
int pl, i; int pl, i;
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
const EVP_MD *md5 = md5_hash;
#else
const EVP_MD *md5 = EVP_md5();
#endif
if(md5 == NULL) {
*passwd = 0;
return NULL;
}
sp = salt +3; sp = salt +3;
sl = (int)(ep - sp); sl = (int)(ep - sp);
magic = (unsigned char *)"$1$"; magic = (unsigned char *)"$1$";
MD5Init(&ctx); ctx = EVP_MD_CTX_new();
if(!ctx) {
*passwd = 0;
return NULL;
}
EVP_DigestInit_ex(ctx, md5, NULL);
/* The password first, since that is what is most unknown */ /* The password first, since that is what is most unknown */
MD5Update(&ctx,pw,strlen((char *)pw)); EVP_DigestUpdate(ctx,pw,strlen((char *)pw));
/* Then our magic string */ /* Then our magic string */
MD5Update(&ctx,magic,strlen((char *)magic)); EVP_DigestUpdate(ctx,magic,strlen((char *)magic));
/* Then the raw salt */ /* Then the raw salt */
MD5Update(&ctx,sp,sl); EVP_DigestUpdate(ctx,sp,sl);
/* Then just as many unsigned characters of the MD5(pw,salt,pw) */ /* Then just as many unsigned characters of the MD5(pw,salt,pw) */
MD5Init(&ctx1); ctx1 = EVP_MD_CTX_new();
MD5Update(&ctx1,pw,strlen((char *)pw)); if(!ctx1) {
MD5Update(&ctx1,sp,sl); EVP_MD_CTX_free(ctx);
MD5Update(&ctx1,pw,strlen((char *)pw)); *passwd = 0;
MD5Final(final,&ctx1); return NULL;
}
EVP_DigestInit_ex(ctx1, md5, NULL);
EVP_DigestUpdate(ctx1,pw,strlen((char *)pw));
EVP_DigestUpdate(ctx1,sp,sl);
EVP_DigestUpdate(ctx1,pw,strlen((char *)pw));
EVP_DigestFinal_ex(ctx1,final,&len);
for(pl = (int)strlen((char *)pw); pl > 0; pl -= MD5_SIZE) for(pl = (int)strlen((char *)pw); pl > 0; pl -= MD5_SIZE)
MD5Update(&ctx,final,pl>MD5_SIZE ? MD5_SIZE : pl); EVP_DigestUpdate(ctx,final,pl>MD5_SIZE ? MD5_SIZE : pl);
/* Don't leave anything around in vm they could use. */ /* Don't leave anything around in vm they could use. */
memset(final,0,sizeof final); memset(final,0,sizeof final);
@ -109,12 +158,13 @@ unsigned char * mycrypt(const unsigned char *pw, const unsigned char *salt, unsi
/* Then something really weird... */ /* Then something really weird... */
for (i = (int)strlen((char *)pw); i ; i >>= 1) for (i = (int)strlen((char *)pw); i ; i >>= 1)
if(i&1) if(i&1)
MD5Update(&ctx, final, 1); EVP_DigestUpdate(ctx, final, 1);
else else
MD5Update(&ctx, pw, 1); EVP_DigestUpdate(ctx, pw, 1);
MD5Final(final,&ctx); EVP_DigestFinal_ex(ctx,final,&len);
EVP_MD_CTX_free(ctx);
/* /*
* and now, just to make sure things don't run too fast * and now, just to make sure things don't run too fast
@ -122,37 +172,44 @@ unsigned char * mycrypt(const unsigned char *pw, const unsigned char *salt, unsi
* need 30 seconds to build a 1000 entry dictionary... * need 30 seconds to build a 1000 entry dictionary...
*/ */
for(i=0;i<1000;i++) { for(i=0;i<1000;i++) {
MD5Init(&ctx1); EVP_MD_CTX_reset(ctx1);
EVP_DigestInit_ex(ctx1, md5, NULL);
if(i & 1) if(i & 1)
MD5Update(&ctx1,pw,strlen((char *)pw)); EVP_DigestUpdate(ctx1,pw,strlen((char *)pw));
else else
MD5Update(&ctx1,final,MD5_SIZE); EVP_DigestUpdate(ctx1,final,MD5_SIZE);
if(i % 3) if(i % 3)
MD5Update(&ctx1,sp,sl); EVP_DigestUpdate(ctx1,sp,sl);
if(i % 7) if(i % 7)
MD5Update(&ctx1,pw,strlen((char *)pw)); EVP_DigestUpdate(ctx1,pw,strlen((char *)pw));
if(i & 1) if(i & 1)
MD5Update(&ctx1,final,MD5_SIZE); EVP_DigestUpdate(ctx1,final,MD5_SIZE);
else else
MD5Update(&ctx1,pw,strlen((char *)pw)); EVP_DigestUpdate(ctx1,pw,strlen((char *)pw));
MD5Final(final,&ctx1); EVP_DigestFinal_ex(ctx1,final,&len);
} }
EVP_MD_CTX_free(ctx1);
/* Don't leave anything around in vm they could use. */
memset(final,0,sizeof final);
} }
else else
#endif
#endif #endif
if(salt[0] == '$' && salt[1] == '3' && salt[2] == '$' && (ep = (unsigned char *)strchr((char *)salt+3, '$'))) { if(salt[0] == '$' && salt[1] == '3' && salt[2] == '$' && (ep = (unsigned char *)strchr((char *)salt+3, '$'))) {
sp = salt +3; sp = salt +3;
sl = (int)(ep - sp); sl = (int)(ep - sp);
magic = (unsigned char *)"$3$"; magic = (unsigned char *)"$3$";
{
blake2b(final, MD5_SIZE, pw, strlen((char *)pw), salt, strlen((char *)salt) ); blake2b_state S;
if(blake2b_init(&S, MD5_SIZE) != 0 ||
blake2b_update(&S, pw, strlen((char *)pw) + 1) != 0 ||
blake2b_update(&S, sp, sl) != 0 ||
blake2b_final(&S, final, MD5_SIZE) != 0) {
*passwd = 0;
return NULL;
}
}
} }
else { else {
*passwd = 0; *passwd = 0;
@ -181,31 +238,55 @@ unsigned char * mycrypt(const unsigned char *pw, const unsigned char *salt, unsi
} }
#ifdef WITHMAIN #ifdef WITHMAIN
#if defined(WITH_SSL) && OPENSSL_VERSION_NUMBER >= 0x30000000L
#include <openssl/provider.h>
#endif
#include <stdio.h> #include <stdio.h>
int main(int argc, char* argv[]){ int main(int argc, char* argv[]){
unsigned char buf[1024]; unsigned char buf1[128];
unsigned char buf2[128];
unsigned i; unsigned i;
if(argc < 2 || argc > 3) { if(argc < 2 || argc > 3) {
fprintf(stderr, "usage: \n" fprintf(stderr, "usage: \n"
#ifdef WITH_SSL
"\t%s <password>\n" "\t%s <password>\n"
#endif
"\t%s <salt> <password>\n" "\t%s <salt> <password>\n"
#ifdef WITH_SSL
"Performs NT crypt if no salt specified, BLAKE2 crypt with salt\n" "Performs NT crypt if no salt specified, BLAKE2 crypt with salt\n"
"This software uses:\n" #else
" RSA Data Security, Inc. MD4 Message-Digest Algorithm\n" "Performs BLAKE2 crypt with salt\n"
" RSA Data Security, Inc. MD5 Message-Digest Algorithm\n", #endif
,
#ifdef WITH_SSL
argv[0], argv[0],
#endif
argv[0]); argv[0]);
return 1; return 1;
} }
#if defined(WITH_SSL) && OPENSSL_VERSION_NUMBER >= 0x30000000L
OSSL_PROVIDER_load(NULL, "legacy");
OSSL_PROVIDER_load(NULL, "default");
md4_hash = EVP_MD_fetch(NULL, "MD4", NULL);
if (md4_hash == NULL) {
fprintf(stderr, "Error fetching MD4\n");
}
#endif
if(argc == 2) { if(argc == 2) {
printf("NT:%s\n", ntpwdhash(buf, (unsigned char *)argv[1], 1)); #ifdef WITH_SSL
{ unsigned char *nt = ntpwdhash(buf1, (unsigned char *)argv[1], 1);
if(nt) printf("NT:%s\n", nt); }
#else
fprintf(stderr, "NT crypt not available (compiled without OpenSSL)\n");
#endif
} }
else { else {
unsigned char *cr;
i = (int)strlen((char *)argv[1]); i = (int)strlen((char *)argv[1]);
if (i > 64) argv[1][64] = 0; if (i > 64) argv[1][64] = 0;
sprintf((char *)buf, "$3$%s$", argv[1]); sprintf((char *)buf1, "$3$%.64s$", argv[1]);
printf("CR:%s\n", mycrypt((unsigned char *)argv[2], buf, buf+256)); cr = mycrypt((unsigned char *)argv[2], buf1, buf2);
if(cr) printf("CR:%s\n", cr);
} }
return 0; return 0;
} }

View File

@ -2,12 +2,14 @@
# 3 proxy common Makefile # 3 proxy common Makefile
# #
all: $(BUILDDIR)3proxy$(EXESUFFICS) $(BUILDDIR)3proxy_crypt$(EXESUFFICS) $(BUILDDIR)pop3p$(EXESUFFICS) $(BUILDDIR)smtpp$(EXESUFFICS) $(BUILDDIR)ftppr$(EXESUFFICS) $(BUILDDIR)tcppm$(EXESUFFICS) $(BUILDDIR)tlspr$(EXESUFFICS) $(BUILDDIR)udppm$(EXESUFFICS) $(BUILDDIR)socks$(EXESUFFICS) $(BUILDDIR)proxy$(EXESUFFICS) allplugins 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
sockmap$(OBJSUFFICS): sockmap.c proxy.h structures.h sockmap$(OBJSUFFICS): sockmap.c proxy.h structures.h
$(CC) $(CFLAGS) sockmap.c $(CC) $(CFLAGS) sockmap.c
udpsockmap$(OBJSUFFICS): udpsockmap.c proxy.h structures.h
$(CC) $(COUT)udpsockmap$(OBJSUFFICS) $(CFLAGS) udpsockmap.c
common$(OBJSUFFICS): common.c proxy.h structures.h common$(OBJSUFFICS): common.c proxy.h structures.h
$(CC) $(CFLAGS) common.c $(CC) $(CFLAGS) common.c
@ -20,69 +22,64 @@ base64$(OBJSUFFICS): base64.c
ftp$(OBJSUFFICS): ftp.c proxy.h structures.h ftp$(OBJSUFFICS): ftp.c proxy.h structures.h
$(CC) $(CFLAGS) ftp.c $(CC) $(CFLAGS) ftp.c
#$(COMPATLIBS):
# $(CC) $(CFLAGS) strncasecmp.c
sockgetchar$(OBJSUFFICS): sockgetchar.c proxy.h structures.h sockgetchar$(OBJSUFFICS): sockgetchar.c proxy.h structures.h
$(CC) $(CFLAGS) sockgetchar.c $(CC) $(CFLAGS) sockgetchar.c
proxy$(OBJSUFFICS): proxy.c proxy.h structures.h proxymain.c proxy$(OBJSUFFICS): proxy.c proxy.h structures.h proxymain.c
$(CC) $(CFLAGS) $(DEFINEOPTION)WITHMAIN $(DEFINEOPTION)NOPORTMAP $(DEFINEOPTION)ANONYMOUS proxy.c $(CC) $(CFLAGS) $(DEFINEOPTION)WITHMAIN $(DEFINEOPTION)NOPORTMAP $(DEFINEOPTION)ANONYMOUS $(DEFINEOPTION)NOUDPMAIN proxy.c
pop3p$(OBJSUFFICS): pop3p.c proxy.h structures.h proxymain.c pop3p$(OBJSUFFICS): pop3p.c proxy.h structures.h proxymain.c
$(CC) $(CFLAGS) $(DEFINEOPTION)WITHMAIN $(DEFINEOPTION)NOPORTMAP pop3p.c $(CC) $(CFLAGS) $(DEFINEOPTION)WITHMAIN $(DEFINEOPTION)NOPORTMAP $(DEFINEOPTION)NOUDPMAIN pop3p.c
smtpp$(OBJSUFFICS): smtpp.c proxy.h structures.h proxymain.c smtpp$(OBJSUFFICS): smtpp.c proxy.h structures.h proxymain.c
$(CC) $(CFLAGS) $(DEFINEOPTION)WITHMAIN $(DEFINEOPTION)NOPORTMAP smtpp.c $(CC) $(CFLAGS) $(DEFINEOPTION)WITHMAIN $(DEFINEOPTION)NOPORTMAP $(DEFINEOPTION)NOUDPMAIN smtpp.c
ftppr$(OBJSUFFICS): ftppr.c proxy.h structures.h proxymain.c ftppr$(OBJSUFFICS): ftppr.c proxy.h structures.h proxymain.c
$(CC) $(CFLAGS) $(DEFINEOPTION)WITHMAIN $(DEFINEOPTION)NOPORTMAP ftppr.c $(CC) $(CFLAGS) $(DEFINEOPTION)WITHMAIN $(DEFINEOPTION)NOPORTMAP $(DEFINEOPTION)NOUDPMAIN ftppr.c
tcppm$(OBJSUFFICS): tcppm.c proxy.h structures.h proxymain.c tcppm$(OBJSUFFICS): tcppm.c proxy.h structures.h proxymain.c
$(CC) $(CFLAGS) $(DEFINEOPTION)WITHMAIN $(DEFINEOPTION)PORTMAP tcppm.c $(CC) $(CFLAGS) $(DEFINEOPTION)WITHMAIN $(DEFINEOPTION)PORTMAP $(DEFINEOPTION)NOUDPMAIN tcppm.c
tlspr$(OBJSUFFICS): tlspr.c proxy.h structures.h proxymain.c
$(CC) $(CFLAGS) $(DEFINEOPTION)WITHMAIN $(DEFINEOPTION)PORTMAP tlspr.c
socks$(OBJSUFFICS): socks.c proxy.h structures.h proxymain.c
$(CC) $(CFLAGS) $(DEFINEOPTION)WITHMAIN $(DEFINEOPTION)NOPORTMAP socks.c
udppm$(OBJSUFFICS): udppm.c proxy.h structures.h proxymain.c udppm$(OBJSUFFICS): udppm.c proxy.h structures.h proxymain.c
$(CC) $(CFLAGS) $(DEFINEOPTION)WITHMAIN $(DEFINEOPTION)PORTMAP udppm.c $(CC) $(CFLAGS) $(DEFINEOPTION)WITHMAIN $(DEFINEOPTION)PORTMAP udppm.c
tlspr$(OBJSUFFICS): tlspr.c proxy.h structures.h proxymain.c
$(CC) $(CFLAGS) $(DEFINEOPTION)WITHMAIN $(DEFINEOPTION)PORTMAP $(DEFINEOPTION)NOUDPMAIN tlspr.c
socks$(OBJSUFFICS): socks.c proxy.h structures.h proxymain.c
$(CC) $(CFLAGS) $(DEFINEOPTION)WITHMAIN $(DEFINEOPTION)NOPORTMAP $(DEFINEOPTION)NOUDPMAIN socks.c
3proxy$(OBJSUFFICS): 3proxy.c proxy.h structures.h 3proxy$(OBJSUFFICS): 3proxy.c proxy.h structures.h
$(CC) $(CFLAGS) 3proxy.c $(CC) $(CFLAGS) 3proxy.c
$(BUILDDIR)proxy$(EXESUFFICS): sockmap$(OBJSUFFICS) proxy$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) $(COMPATLIBS) $(BUILDDIR)$(PREFIX)proxy$(EXESUFFICS): sockmap$(OBJSUFFICS) proxy$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) $(COMPATLIBS)
$(LN) $(LNOUT)$(BUILDDIR)proxy$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) proxy$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) $(COMPATLIBS) $(LIBS) $(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)proxy$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) proxy$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)
$(BUILDDIR)pop3p$(EXESUFFICS): sockmap$(OBJSUFFICS) pop3p$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) $(COMPATLIBS) $(BUILDDIR)$(PREFIX)pop3p$(EXESUFFICS): sockmap$(OBJSUFFICS) pop3p$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) $(COMPATLIBS)
$(LN) $(LNOUT)$(BUILDDIR)pop3p$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) pop3p$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) $(COMPATLIBS) $(LIBS) $(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)pop3p$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) pop3p$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)
$(BUILDDIR)smtpp$(EXESUFFICS): sockmap$(OBJSUFFICS) smtpp$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) base64$(OBJSUFFICS) $(COMPATLIBS) $(BUILDDIR)$(PREFIX)smtpp$(EXESUFFICS): sockmap$(OBJSUFFICS) smtpp$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) base64$(OBJSUFFICS) $(COMPATLIBS)
$(LN) $(LNOUT)$(BUILDDIR)smtpp$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) smtpp$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) base64$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) $(COMPATLIBS) $(LIBS) $(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)smtpp$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) smtpp$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) base64$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)
$(BUILDDIR)ftppr$(EXESUFFICS): sockmap$(OBJSUFFICS) ftppr$(OBJSUFFICS) ftp$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) $(COMPATLIBS) $(BUILDDIR)$(PREFIX)ftppr$(EXESUFFICS): sockmap$(OBJSUFFICS) ftppr$(OBJSUFFICS) ftp$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) $(COMPATLIBS)
$(LN) $(LNOUT)$(BUILDDIR)ftppr$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) ftppr$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) ftp$(OBJSUFFICS) $(COMPATLIBS) $(LIBS) $(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)ftppr$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) ftppr$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) ftp$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)
$(BUILDDIR)socks$(EXESUFFICS): sockmap$(OBJSUFFICS) socks$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) $(BUILDDIR)$(PREFIX)socks$(EXESUFFICS): sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) socks$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS)
$(LN) $(LNOUT)$(BUILDDIR)socks$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) socks$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) $(LIBS) $(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)socks$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) socks$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) $(LIBS)
$(BUILDDIR)tcppm$(EXESUFFICS): sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) tcppm$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) $(BUILDDIR)$(PREFIX)tcppm$(EXESUFFICS): sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) tcppm$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS)
$(LN) $(LNOUT)$(BUILDDIR)tcppm$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) tcppm$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) $(LIBS) $(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)tcppm$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) tcppm$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) $(LIBS)
$(BUILDDIR)tlspr$(EXESUFFICS): sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) tlspr$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) $(BUILDDIR)$(PREFIX)udppm$(EXESUFFICS): sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) udppm$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) hash$(OBJSUFFICS)
$(LN) $(LNOUT)$(BUILDDIR)tlspr$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) tlspr$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) $(LIBS) $(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)udppm$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) udppm$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) hash$(OBJSUFFICS) $(LIBS)
$(BUILDDIR)udppm$(EXESUFFICS): sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) udppm$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) $(BUILDDIR)$(PREFIX)tlspr$(EXESUFFICS): sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) tlspr$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS)
$(LN) $(LNOUT)$(BUILDDIR)udppm$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) udppm$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) $(LIBS) $(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)tlspr$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) tlspr$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) $(LIBS)
mainfunc$(OBJSUFFICS): proxy.h structures.h proxymain.c mainfunc$(OBJSUFFICS): proxy.h structures.h proxymain.c
$(CC) $(COUT)mainfunc$(OBJSUFFICS) $(CFLAGS) $(DEFINEOPTION)MODULEMAINFUNC=mainfunc proxymain.c $(CC) $(COUT)mainfunc$(OBJSUFFICS) $(CFLAGS) $(DEFINEOPTION)MODULEMAINFUNC=mainfunc proxymain.c
srvproxy$(OBJSUFFICS): proxy.c proxy.h structures.h srvproxy$(OBJSUFFICS): proxy.c proxy.h structures.h
$(CC) $(COUT)srvproxy$(OBJSUFFICS) $(CFLAGS) proxy.c $(CC) $(COUT)srvproxy$(OBJSUFFICS) $(CFLAGS) proxy.c
@ -119,9 +116,21 @@ srvdnspr$(OBJSUFFICS): dnspr.c proxy.h structures.h
auth$(OBJSUFFICS): auth.c proxy.h structures.h auth$(OBJSUFFICS): auth.c proxy.h structures.h
$(CC) $(COUT)auth$(OBJSUFFICS) $(CFLAGS) auth.c $(CC) $(COUT)auth$(OBJSUFFICS) $(CFLAGS) auth.c
acl$(OBJSUFFICS): acl.c proxy.h structures.h
$(CC) $(COUT)acl$(OBJSUFFICS) $(CFLAGS) acl.c
limiter$(OBJSUFFICS): limiter.c proxy.h structures.h
$(CC) $(COUT)limiter$(OBJSUFFICS) $(CFLAGS) limiter.c
redirect$(OBJSUFFICS): redirect.c proxy.h structures.h
$(CC) $(COUT)redirect$(OBJSUFFICS) $(CFLAGS) redirect.c
hash$(OBJSUFFICS): hash.c proxy.h structures.h hash$(OBJSUFFICS): hash.c proxy.h structures.h
$(CC) $(COUT)hash$(OBJSUFFICS) $(CFLAGS) hash.c $(CC) $(COUT)hash$(OBJSUFFICS) $(CFLAGS) hash.c
hashtables$(OBJSUFFICS): hashtables.c proxy.h structures.h libs/blake2.h
$(CC) $(COUT)hashtables$(OBJSUFFICS) $(CFLAGS) hashtables.c
resolve$(OBJSUFFICS): resolve.c proxy.h structures.h resolve$(OBJSUFFICS): resolve.c proxy.h structures.h
$(CC) $(COUT)resolve$(OBJSUFFICS) $(CFLAGS) resolve.c $(CC) $(COUT)resolve$(OBJSUFFICS) $(CFLAGS) resolve.c
@ -137,27 +146,30 @@ log$(OBJSUFFICS): log.c proxy.h structures.h
datatypes$(OBJSUFFICS): datatypes.c proxy.h structures.h datatypes$(OBJSUFFICS): datatypes.c proxy.h structures.h
$(CC) $(COUT)datatypes$(OBJSUFFICS) $(CFLAGS) datatypes.c $(CC) $(COUT)datatypes$(OBJSUFFICS) $(CFLAGS) datatypes.c
3proxy_crypt$(OBJSUFFICS): 3proxy_crypt.c 3proxy_crypt$(OBJSUFFICS): 3proxy_crypt.c libs/blake2.h
$(CC) $(COUT)3proxy_crypt$(OBJSUFFICS) $(CFLAGS) 3proxy_crypt.c $(CC) $(COUT)3proxy_crypt$(OBJSUFFICS) $(CFLAGS) 3proxy_crypt.c
3proxy_cryptmain$(OBJSUFFICS): 3proxy_crypt.c 3proxy_cryptmain$(OBJSUFFICS): 3proxy_crypt.c libs/blake2.h
$(CC) $(COUT)3proxy_cryptmain$(OBJSUFFICS) $(CFLAGS) $(DEFINEOPTION)WITHMAIN 3proxy_crypt.c $(CC) $(COUT)3proxy_cryptmain$(OBJSUFFICS) $(CFLAGS) $(DEFINEOPTION)WITHMAIN 3proxy_crypt.c
md4$(OBJSUFFICS): libs/md4.h libs/md4.c blake2$(OBJSUFFICS): libs/blake2b-ref.c
$(CC) $(COUT)md4$(OBJSUFFICS) $(CFLAGS) libs/md4.c
md5$(OBJSUFFICS): libs/md5.h libs/md5.c
$(CC) $(COUT)md5$(OBJSUFFICS) $(CFLAGS) libs/md5.c
blake2$(OBJSUFFICS): libs/blake2.h libs/blake2-impl.h libs/blake2b-ref.c
$(CC) $(COUT)blake2$(OBJSUFFICS) $(CFLAGS) libs/blake2b-ref.c $(CC) $(COUT)blake2$(OBJSUFFICS) $(CFLAGS) libs/blake2b-ref.c
$(BUILDDIR)3proxy_crypt$(EXESUFFICS): md4$(OBJSUFFICS) blake2$(OBJSUFFICS) 3proxy_cryptmain$(OBJSUFFICS) base64$(OBJSUFFICS) $(BUILDDIR)$(CRYPT_PREFIX)crypt$(EXESUFFICS): blake2$(OBJSUFFICS) 3proxy_cryptmain$(OBJSUFFICS) base64$(OBJSUFFICS)
$(LN) $(LNOUT)$(BUILDDIR)3proxy_crypt$(EXESUFFICS) $(LDFLAGS) md4$(OBJSUFFICS) blake2$(OBJSUFFICS) base64$(OBJSUFFICS) 3proxy_cryptmain$(OBJSUFFICS) $(LN) $(LNOUT)$(BUILDDIR)$(CRYPT_PREFIX)crypt$(EXESUFFICS) $(LDFLAGS) blake2$(OBJSUFFICS) base64$(OBJSUFFICS) 3proxy_cryptmain$(OBJSUFFICS) $(LIBS)
stringtable$(OBJSUFFICS): stringtable.c stringtable$(OBJSUFFICS): stringtable.c
$(CC) $(COUT)stringtable$(OBJSUFFICS) $(CFLAGS) stringtable.c $(CC) $(COUT)stringtable$(OBJSUFFICS) $(CFLAGS) stringtable.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) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) auth$(OBJSUFFICS) authradius$(OBJSUFFICS) hash$(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) $(COMPATLIBS) $(VERSIONDEP) ssllib$(OBJSUFFICS): ssllib.c structures.h proxy.h ssl.h
$(LN) $(LNOUT)$(BUILDDIR)3proxy$(EXESUFFICS) $(LDFLAGS) $(VERFILE) 3proxy$(OBJSUFFICS) mainfunc$(OBJSUFFICS) auth$(OBJSUFFICS) authradius$(OBJSUFFICS) hash$(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) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) 3proxy_crypt$(OBJSUFFICS) md5$(OBJSUFFICS) blake2$(OBJSUFFICS) md4$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) stringtable$(OBJSUFFICS) srvwebadmin$(OBJSUFFICS) srvdnspr$(OBJSUFFICS) plugins$(OBJSUFFICS) $(COMPATLIBS) $(LIBS) $(CC) $(COUT)ssllib$(OBJSUFFICS) $(CFLAGS) ssllib.c
ssl$(OBJSUFFICS): ssl.c structures.h proxy.h ssl.h
$(CC) $(COUT)ssl$(OBJSUFFICS) $(CFLAGS) ssl.c
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) blake2$(OBJSUFFICS) 3proxy_crypt$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) stringtable$(OBJSUFFICS) srvwebadmin$(OBJSUFFICS) srvdnspr$(OBJSUFFICS) plugins$(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) blake2$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) stringtable$(OBJSUFFICS) srvwebadmin$(OBJSUFFICS) srvdnspr$(OBJSUFFICS) plugins$(OBJSUFFICS) $(SSL_OBJS) $(PCRE_OBJS) $(COMPATLIBS) $(LIBS) $(PCRE_LIBS)

169
src/acl.c Normal file
View File

@ -0,0 +1,169 @@
/*
3APA3A simplest proxy server
(c) 2002-2026 by Vladimir Dubrovin <vlad@3proxy.org>
please read License Agreement
*/
#include "proxy.h"
int IPInentry(struct sockaddr *sa, struct iplist *ipentry){
int addrlen;
unsigned char *ip, *ipf, *ipt;
if(!sa || ! ipentry || *SAFAMILY(sa) != ipentry->family) return 0;
ip = (unsigned char *)SAADDR(sa);
ipf = (unsigned char *)&ipentry->ip_from;
ipt = (unsigned char *)&ipentry->ip_to;
addrlen = SAADDRLEN(sa);
if(memcmp(ip,ipf,addrlen) < 0 || memcmp(ip,ipt,addrlen) > 0) return 0;
return 1;
}
int ACLmatches(struct ace* acentry, struct clientparam * param){
struct userlist * userentry;
struct iplist *ipentry;
struct portlist *portentry;
struct period *periodentry;
unsigned char * username;
struct hostname * hstentry=NULL;
int i;
int match = 0;
username = param->username?param->username:(unsigned char *)"-";
if(acentry->src) {
for(ipentry = acentry->src; ipentry; ipentry = ipentry->next)
if(IPInentry((struct sockaddr *)&param->sincr, ipentry)) {
break;
}
if(!ipentry) return 0;
}
if((acentry->dst && (!SAISNULL(&param->req) || param->operation==BIND)) || (acentry->dstnames && param->hostname)) {
for(ipentry = acentry->dst; ipentry; ipentry = ipentry->next)
if(IPInentry((struct sockaddr *)&param->req, ipentry)) {
break;
}
if(!ipentry) {
if(acentry->dstnames && param->hostname){
for(i=0; param->hostname[i]; i++){
param->hostname[i] = tolower(param->hostname[i]);
}
while(i > 5 && param->hostname[i-1] == '.') param->hostname[i-1] = 0;
for(hstentry = acentry->dstnames; hstentry; hstentry = hstentry->next){
int lname, lhost;
switch(hstentry->matchtype){
case 0:
#ifndef _WIN32
if(strcasestr((char *)param->hostname, (char *)hstentry->name)) match = 1;
#else
if(strstr((char *)param->hostname, (char *)hstentry->name)) match = 1;
#endif
break;
case 1:
if(!strncasecmp((char *)param->hostname, (char *)hstentry->name, strlen((char *)hstentry->name)))
match = 1;
break;
case 2:
lname = strlen((char *)hstentry->name);
lhost = strlen((char *)param->hostname);
if(lhost > lname){
if(!strncasecmp((char *)param->hostname + (lhost - lname),
(char *)hstentry->name,
lname))
match = 1;
}
break;
default:
if(!strcasecmp((char *)param->hostname, (char *)hstentry->name)) match = 1;
break;
}
if(match) break;
}
}
}
if(!ipentry && !hstentry) return 0;
}
if(acentry->ports && (*SAPORT(&param->req) || param->operation == BIND)) {
for (portentry = acentry->ports; portentry; portentry = portentry->next)
if(ntohs(*SAPORT(&param->req)) >= portentry->startport &&
ntohs(*SAPORT(&param->req)) <= portentry->endport) {
break;
}
if(!portentry) return 0;
}
if(acentry->wdays){
if(!(acentry -> wdays & wday)) return 0;
}
if(acentry->periods){
int start_time = (int)(param->time_start - basetime);
for(periodentry = acentry->periods; periodentry; periodentry = periodentry -> next)
if(start_time >= periodentry->fromtime && start_time < periodentry->totime){
break;
}
if(!periodentry) return 0;
}
if(acentry->users){
for(userentry = acentry->users; userentry; userentry = userentry->next)
if(!strcmp((char *)username, (char *)userentry->user)){
break;
}
if(!userentry) return 0;
}
if(acentry->operation) {
if((acentry->operation & param->operation) != param->operation){
return 0;
}
}
if(acentry->weight && (acentry->weight < param->weight)) return 0;
return 1;
}
int checkACL(struct clientparam * param){
struct ace* acentry;
if(!param->srv->acl) {
return 0;
}
for(acentry = param->srv->acl; acentry; acentry = acentry->next) {
if(ACLmatches(acentry, param)) {
param->nolog = acentry->nolog;
param->weight = acentry->weight;
if(acentry->action == 2) {
struct ace dup;
int res=60,i=0;
if(param->operation < 256 && !(param->operation & (CONNECT|UDPASSOC))){
continue;
}
if(param->redirected && acentry->chains && SAISNULL(&acentry->chains->addr) && !*SAPORT(&acentry->chains->addr)) {
continue;
}
if(param->remsock != INVALID_SOCKET && (param->operation != UDPASSOC || param->ctrlsocksrv != INVALID_SOCKET)) {
return 0;
}
for(; i < conf.parentretries; i++){
dup = *acentry;
res = handleredirect(param, &dup);
if(!res) break;
if(param->remsock != INVALID_SOCKET) param->srv->so._closesocket(param->sostate, param->remsock);
param->remsock = INVALID_SOCKET;
}
return res;
}
return acentry->action;
}
}
return 3;
}

View File

@ -1,683 +1,15 @@
/* /*
3APA3A simplest proxy server 3APA3A simplest proxy server
(c) 2002-2021 by Vladimir Dubrovin <3proxy@3proxy.org> (c) 2002-2026 by Vladimir Dubrovin <vlad@3proxy.org>
please read License Agreement please read License Agreement
*/ */
#include "proxy.h" #include "proxy.h"
#include "libs/blake2.h"
static FILTER_ACTION (*ext_ssl_parent)(struct clientparam * param) = NULL; void initbandlims(struct clientparam *param);
static FILTER_ACTION ssl_parent(struct clientparam * param){
if(ext_ssl_parent) return ext_ssl_parent(param);
ext_ssl_parent = pluginlink.findbyname("ssl_parent");
if(ext_ssl_parent) return ext_ssl_parent(param);
return REJECT;
}
int clientnegotiate(struct chain * redir, struct clientparam * param, struct sockaddr * addr, unsigned char * hostname){
unsigned char *buf;
unsigned char *username;
int res;
int len=0;
unsigned char * user, *pass;
user = redir->extuser;
pass = redir->extpass;
if (!param->srvbufsize){
param->srvbufsize = SRVBUFSIZE;
param->srvbuf = myalloc(param->srvbufsize);
if(!param->srvbuf) return 21;
}
buf = param->srvbuf;
username = buf + 2048;
if(user) {
if (*user == '*') {
if(!param->username) return 4;
user = param->username;
pass = param->password;
}
}
if(redir->secure){
res = ssl_parent(param);
if(res != PASS) return res;
}
switch(redir->type){
case R_TCP:
case R_HTTP:
return 0;
case R_CONNECT:
case R_CONNECTP:
{
len = sprintf((char *)buf, "CONNECT ");
if(redir->type == R_CONNECTP && hostname) {
char * needreplace;
needreplace = strchr((char *)hostname, ':');
if(needreplace) buf[len++] = '[';
len += sprintf((char *)buf + len, "%.256s", (char *)hostname);
if(needreplace) buf[len++] = ']';
}
else {
if(*SAFAMILY(addr) == AF_INET6) buf[len++] = '[';
len += myinet_ntop(*SAFAMILY(addr), SAADDR(addr), (char *)buf+len, 256);
if(*SAFAMILY(addr) == AF_INET6) buf[len++] = ']';
}
len += sprintf((char *)buf + len,
":%hu HTTP/1.0\r\nConnection: keep-alive\r\n", ntohs(*SAPORT(addr)));
if(user){
len += sprintf((char *)buf + len, "Proxy-Authorization: Basic ");
sprintf((char *)username, "%.128s:%.128s", user, pass?pass:(unsigned char *)"");
en64(username, buf+len, (int)strlen((char *)username));
len = (int)strlen((char *)buf);
len += sprintf((char *)buf + len, "\r\n");
}
len += sprintf((char *)buf + len, "\r\n");
if(socksend(param, param->remsock, buf, len, conf.timeouts[CHAIN_TO]) != (int)strlen((char *)buf))
return 31;
param->statssrv64+=len;
param->nwrites++;
if((res = sockgetlinebuf(param, SERVER,buf,13,'\n',conf.timeouts[CHAIN_TO])) < 13)
return 32;
if(buf[9] != '2') return 33;
while((res = sockgetlinebuf(param, SERVER,buf,1023,'\n', conf.timeouts[CHAIN_TO])) > 2);
if(res <= 0) return 34;
return 0;
}
case R_SOCKS4:
case R_SOCKS4P:
case R_SOCKS4B:
{
if(*SAFAMILY(addr) != AF_INET) return 44;
buf[0] = 4;
buf[1] = 1;
memcpy(buf+2, SAPORT(addr), 2);
if(redir->type == R_SOCKS4P && hostname) {
buf[4] = buf[5] = buf[6] = 0;
buf[7] = 3;
}
else memcpy(buf+4, SAADDR(addr), 4);
if(!user)user = (unsigned char *)"anonymous";
len = (int)strlen((char *)user) + 1;
memcpy(buf+8, user, len);
len += 8;
if(redir->type == R_SOCKS4P && hostname) {
int hostnamelen;
hostnamelen = (int)strlen((char *)hostname) + 1;
if(hostnamelen > 255) hostnamelen = 255;
memcpy(buf+len, hostname, hostnamelen);
len += hostnamelen;
}
if(socksend(param, param->remsock, buf, len, conf.timeouts[CHAIN_TO]) < len){
return 41;
}
param->statssrv64+=len;
param->nwrites++;
if((len = sockgetlinebuf(param, SERVER, buf, (redir->type == R_SOCKS4B)? 3:8, EOF, conf.timeouts[CHAIN_TO])) != ((redir->type == R_SOCKS4B)? 3:8)){
return 42;
}
if(buf[1] != 90) {
return 43;
}
}
return 0;
case R_SOCKS5:
case R_SOCKS5P:
case R_SOCKS5B:
{
int inbuf = 0;
buf[0] = 5;
buf[1] = 1;
buf[2] = user? 2 : 0;
if(socksend(param, param->remsock, buf, 3, conf.timeouts[CHAIN_TO]) != 3){
return 51;
}
param->statssrv64+=len;
param->nwrites++;
if(sockgetlinebuf(param, SERVER, buf, 2, EOF, conf.timeouts[CHAIN_TO]) != 2){
return 52;
}
if(buf[0] != 5) {
return 53;
}
if(buf[1] != 0 && !(buf[1] == 2 && user)){
return 54;
}
if(buf[1] == 2){
buf[inbuf++] = 1;
buf[inbuf] = (unsigned char)strlen((char *)user);
memcpy(buf+inbuf+1, user, buf[inbuf]);
inbuf += buf[inbuf] + 1;
buf[inbuf] = pass?(unsigned char)strlen((char *)pass):0;
if(pass)memcpy(buf+inbuf+1, pass, buf[inbuf]);
inbuf += buf[inbuf] + 1;
if(socksend(param, param->remsock, buf, inbuf, conf.timeouts[CHAIN_TO]) != inbuf){
return 51;
}
param->statssrv64+=inbuf;
param->nwrites++;
if(sockgetlinebuf(param, SERVER, buf, 2, EOF, 60) != 2){
return 55;
}
if(buf[0] != 1 || buf[1] != 0) {
return 56;
}
}
buf[0] = 5;
buf[1] = 1;
buf[2] = 0;
if(redir->type == R_SOCKS5P && hostname) {
buf[3] = 3;
len = (int)strlen((char *)hostname);
if(len > 255) len = 255;
buf[4] = len;
memcpy(buf + 5, hostname, len);
len += 5;
}
else {
len = 3;
buf[len++] = (*SAFAMILY(addr) == AF_INET)? 1 : 4;
memcpy(buf+len, SAADDR(addr), SAADDRLEN(addr));
len += SAADDRLEN(addr);
}
memcpy(buf+len, SAPORT(addr), 2);
len += 2;
if(socksend(param, param->remsock, buf, len, conf.timeouts[CHAIN_TO]) != len){
return 51;
}
param->statssrv64+=len;
param->nwrites++;
if(sockgetlinebuf(param, SERVER, buf, 4, EOF, conf.timeouts[CHAIN_TO]) != 4){
return 57;
}
if(buf[0] != 5) {
return 53;
}
if(buf[1] != 0) {
return 60 + (buf[1] % 10);
}
switch (buf[3]) {
case 1:
if (redir->type == R_SOCKS5B || sockgetlinebuf(param, SERVER, buf, 6, EOF, conf.timeouts[CHAIN_TO]) == 6)
break;
return 59;
case 3:
if (sockgetlinebuf(param, SERVER, buf, 1, EOF, conf.timeouts[CHAIN_TO]) != 1) return 59;
len = (unsigned char)buf[0];
if (sockgetlinebuf(param, SERVER, buf, len + 2, EOF, conf.timeouts[CHAIN_TO]) != len + 2) return 59;
break;
case 4:
if (sockgetlinebuf(param, SERVER, buf, 18, EOF, conf.timeouts[CHAIN_TO]) == 18)
break;
return 59;
default:
return 58;
}
return 0;
}
default:
return 30;
}
}
int handleredirect(struct clientparam * param, struct ace * acentry){
int connected = 0;
int weight = 1000;
int res;
int done = 0;
int ha = 0;
struct chain * cur;
struct chain * redir = NULL;
int r2;
if(param->remsock != INVALID_SOCKET) {
return 0;
}
if(SAISNULL(&param->req) || !*SAPORT(&param->req)) {
return 100;
}
r2 = (myrand(param, sizeof(struct clientparam))%1000);
for(cur = acentry->chains; cur; cur=cur->next){
if(((weight = weight - cur->weight) > r2)|| done) {
if(weight <= 0) {
weight += 1000;
done = 0;
r2 = (myrand(param, sizeof(struct clientparam))%1000);
}
continue;
}
param->redirected++;
done = 1;
if(weight <= 0) {
weight += 1000;
done = 0;
r2 = (myrand(param, sizeof(struct clientparam))%1000);
}
if(!connected){
if(cur->type == R_EXTIP){
param->sinsl = cur->addr;
if(SAISNULL(&param->sinsl) && (*SAFAMILY(&param->sincr) == AF_INET || *SAFAMILY(&param->sincr) == AF_INET6))param->sinsl = param->sincr;
#ifndef NOIPV6
else if(cur->cidr && *SAFAMILY(&param->sinsl) == AF_INET6){
uint16_t c;
int i;
for(i = 0; i < 8; i++){
if(i==4)myrand(&param->sincr, sizeof(param->sincr));
else if(i==6) myrand(&param->req, sizeof(param->req));
if(i*16 >= cur->cidr) ((uint16_t *)SAADDR(&param->sinsl))[i] |= rand();
else if ((i+1)*16 > cur->cidr){
c = rand();
c >>= (cur->cidr - (i*16));
c |= ntohs(((uint16_t *)SAADDR(&param->sinsl))[i]);
((uint16_t *)SAADDR(&param->sinsl))[i] = htons(c);
}
}
}
#endif
if(cur->next)continue;
return 0;
}
else if(SAISNULL(&cur->addr) && !*SAPORT(&cur->addr)){
int i;
if(cur->extuser){
if(param->extusername)
myfree(param->extusername);
param->extusername = (unsigned char *)mystrdup((char *)((*cur->extuser == '*' && param->username)? param->username : cur->extuser));
if(cur->extpass){
if(param->extpassword)
myfree(param->extpassword);
param->extpassword = (unsigned char *)mystrdup((char *)((*cur->extuser == '*' && param->password)?param->password : cur->extpass));
}
if(*cur->extuser == '*' && !param->username) return 4;
}
for(i=0; redirs[i].name; i++){
if(cur->type == redirs[i].redir) {
param->redirectfunc = redirs[i].func;
break;
}
}
if(cur->type == R_HA){
ha = 1;
}
if(cur->next)continue;
if(!ha) return 0;
}
else if(!*SAPORT(&cur->addr) && !SAISNULL(&cur->addr)) {
uint16_t port = *SAPORT(&param->sinsr);
param->sinsr = cur->addr;
*SAPORT(&param->sinsr) = port;
}
else if(SAISNULL(&cur->addr) && *SAPORT(&cur->addr)) *SAPORT(&param->sinsr) = *SAPORT(&cur->addr);
else {
param->sinsr = cur->addr;
}
if((res = alwaysauth(param))){
return (res >= 10)? res : 60+res;
}
if(ha) {
char buf[128];
int len;
len = sprintf(buf, "PROXY %s ",
*SAFAMILY(&param->sincr) == AF_INET6 ? "TCP6" : "TCP4");
len += myinet_ntop(*SAFAMILY(&param->sincr), SAADDR(&param->sincr), buf+len, sizeof(param->sincr));
buf[len++] = ' ';
len += myinet_ntop(*SAFAMILY(&param->sincl), SAADDR(&param->sincl), buf+len, sizeof(param->sincl));
len += sprintf(buf + len, " %hu %hu\r\n",
ntohs(*SAPORT(&param->sincr)),
ntohs(*SAPORT(&param->sincl))
);
if(socksend(param, param->remsock, (unsigned char *)buf, len, conf.timeouts[CHAIN_TO])!=len) return 39;
return 0;
}
}
else {
res = (redir)?clientnegotiate(redir, param, (struct sockaddr *)&cur->addr, cur->exthost):0;
if(res) return res;
}
redir = cur;
param->redirtype = redir->type;
if(redir->type == R_TCP || redir->type ==R_HTTP) {
if(cur->extuser){
if(*cur -> extuser == '*' && !param->username) return 4;
if(param->extusername)
myfree(param->extusername);
param->extusername = (unsigned char *)mystrdup((char *)((*cur->extuser == '*' && param->username)? param->username : cur->extuser));
if(cur->extpass){
if(param->extpassword)
myfree(param->extpassword);
param->extpassword = (unsigned char *)mystrdup((char *)((*cur->extuser == '*' && param->password)?param->password : cur->extpass));
}
}
if(redir->secure) return ssl_parent(param);
return 0;
}
connected = 1;
}
if(!connected || !redir) return 0;
return clientnegotiate(redir, param, (struct sockaddr *)&param->req, param->hostname);
}
int IPInentry(struct sockaddr *sa, struct iplist *ipentry){
int addrlen;
unsigned char *ip, *ipf, *ipt;
if(!sa || ! ipentry || *SAFAMILY(sa) != ipentry->family) return 0;
ip = (unsigned char *)SAADDR(sa);
ipf = (unsigned char *)&ipentry->ip_from;
ipt = (unsigned char *)&ipentry->ip_to;
addrlen = SAADDRLEN(sa);
if(memcmp(ip,ipf,addrlen) < 0 || memcmp(ip,ipt,addrlen) > 0) return 0;
return 1;
}
int ACLmatches(struct ace* acentry, struct clientparam * param){
struct userlist * userentry;
struct iplist *ipentry;
struct portlist *portentry;
struct period *periodentry;
unsigned char * username;
struct hostname * hstentry=NULL;
int i;
int match = 0;
username = param->username?param->username:(unsigned char *)"-";
if(acentry->src) {
for(ipentry = acentry->src; ipentry; ipentry = ipentry->next)
if(IPInentry((struct sockaddr *)&param->sincr, ipentry)) {
break;
}
if(!ipentry) return 0;
}
if((acentry->dst && (!SAISNULL(&param->req) || param->operation == UDPASSOC || param->operation==BIND)) || (acentry->dstnames && param->hostname)) {
for(ipentry = acentry->dst; ipentry; ipentry = ipentry->next)
if(IPInentry((struct sockaddr *)&param->req, ipentry)) {
break;
}
if(!ipentry) {
if(acentry->dstnames && param->hostname){
for(i=0; param->hostname[i]; i++){
param->hostname[i] = tolower(param->hostname[i]);
}
while(i > 5 && param->hostname[i-1] == '.') param->hostname[i-1] = 0;
for(hstentry = acentry->dstnames; hstentry; hstentry = hstentry->next){
int lname, lhost;
switch(hstentry->matchtype){
case 0:
#ifndef _WIN32
if(strcasestr((char *)param->hostname, (char *)hstentry->name)) match = 1;
#else
if(strstr((char *)param->hostname, (char *)hstentry->name)) match = 1;
#endif
break;
case 1:
if(!strncasecmp((char *)param->hostname, (char *)hstentry->name, strlen((char *)hstentry->name)))
match = 1;
break;
case 2:
lname = strlen((char *)hstentry->name);
lhost = strlen((char *)param->hostname);
if(lhost > lname){
if(!strncasecmp((char *)param->hostname + (lhost - lname),
(char *)hstentry->name,
lname))
match = 1;
}
break;
default:
if(!strcasecmp((char *)param->hostname, (char *)hstentry->name)) match = 1;
break;
}
if(match) break;
}
}
}
if(!ipentry && !hstentry) return 0;
}
if(acentry->ports && (*SAPORT(&param->req) || param->operation == UDPASSOC || param->operation == BIND)) {
for (portentry = acentry->ports; portentry; portentry = portentry->next)
if(ntohs(*SAPORT(&param->req)) >= portentry->startport &&
ntohs(*SAPORT(&param->req)) <= portentry->endport) {
break;
}
if(!portentry) return 0;
}
if(acentry->wdays){
if(!(acentry -> wdays & wday)) return 0;
}
if(acentry->periods){
int start_time = (int)(param->time_start - basetime);
for(periodentry = acentry->periods; periodentry; periodentry = periodentry -> next)
if(start_time >= periodentry->fromtime && start_time < periodentry->totime){
break;
}
if(!periodentry) return 0;
}
if(acentry->users){
for(userentry = acentry->users; userentry; userentry = userentry->next)
if(!strcmp((char *)username, (char *)userentry->user)){
break;
}
if(!userentry) return 0;
}
if(acentry->operation) {
if((acentry->operation & param->operation) != param->operation){
return 0;
}
}
if(acentry->weight && (acentry->weight < param->weight)) return 0;
return 1;
}
int startconnlims (struct clientparam *param){
struct connlim * ce;
time_t delta;
uint64_t rating;
int ret = 0;
param->connlim = 1;
pthread_mutex_lock(&connlim_mutex);
for(ce = conf.connlimiter; ce; ce = ce->next) {
if(ACLmatches(ce->ace, param)){
if(ce->ace->action == NOCONNLIM)break;
if(!ce->period){
if(ce->rate <= ce->rating) {
ret = 1;
break;
}
ce->rating++;
continue;
}
delta = conf.time - ce->basetime;
if(ce->period <= delta || ce->basetime > conf.time){
ce->basetime = conf.time;
ce->rating = 0x100000;
continue;
}
rating = delta? ((ce->rating * (ce->period - delta)) / ce->period) + 0x100000 : ce->rating + 0x100000;
if (rating > (ce->rate<<20)) {
ret = 2;
break;
}
ce->rating = rating;
ce->basetime = conf.time;
}
}
pthread_mutex_unlock(&connlim_mutex);
return ret;
}
void stopconnlims (struct clientparam *param){
struct connlim * ce;
pthread_mutex_lock(&connlim_mutex);
for(ce = conf.connlimiter; ce; ce = ce->next) {
if(ACLmatches(ce->ace, param)){
if(ce->ace->action == NOCONNLIM)break;
if(!ce->period && ce->rating){
ce->rating--;
continue;
}
}
}
pthread_mutex_unlock(&connlim_mutex);
}
static void initbandlims (struct clientparam *param){
struct bandlim * be;
int i;
param->bandlimfunc = NULL;
param->bandlims[0] = NULL;
param->bandlimsout[0] = NULL;
if(!conf.bandlimfunc || (!conf.bandlimiter && !conf.bandlimiterout)) return;
for(i=0, be = conf.bandlimiter; be && i<MAXBANDLIMS; be = be->next) {
if(ACLmatches(be->ace, param)){
if(be->ace->action == NOBANDLIM) {
break;
}
param->bandlims[i++] = be;
param->bandlimfunc = conf.bandlimfunc;
}
}
if(i<MAXBANDLIMS)param->bandlims[i] = NULL;
for(i=0, be = conf.bandlimiterout; be && i<MAXBANDLIMS; be = be->next) {
if(ACLmatches(be->ace, param)){
if(be->ace->action == NOBANDLIM) {
break;
}
param->bandlimsout[i++] = be;
param->bandlimfunc = conf.bandlimfunc;
}
}
if(i<MAXBANDLIMS)param->bandlimsout[i] = NULL;
param->bandlimver = conf.bandlimver;
}
unsigned bandlimitfunc(struct clientparam *param, unsigned nbytesin, unsigned nbytesout){
unsigned sleeptime = 0, nsleeptime;
time_t sec;
unsigned msec;
unsigned now;
int i;
#ifdef _WIN32
struct timeb tb;
ftime(&tb);
sec = (unsigned)tb.time;
msec = (unsigned)tb.millitm*1000;
#else
struct timeval tv;
gettimeofday(&tv, NULL);
sec = tv.tv_sec;
msec = tv.tv_usec;
#endif
if(!nbytesin && !nbytesout) return 0;
pthread_mutex_lock(&bandlim_mutex);
if(param->bandlimver != conf.bandlimver){
initbandlims(param);
param->bandlimver = conf.bandlimver;
}
for(i=0; nbytesin&& i<MAXBANDLIMS && param->bandlims[i]; i++){
if( !param->bandlims[i]->basetime ||
param->bandlims[i]->basetime > sec ||
param->bandlims[i]->basetime < (sec - 120)
)
{
param->bandlims[i]->basetime = sec;
param->bandlims[i]->nexttime = 0;
continue;
}
now = (unsigned)((sec - param->bandlims[i]->basetime) * 1000000) + msec;
nsleeptime = (param->bandlims[i]->nexttime > now)?
param->bandlims[i]->nexttime - now : 0;
sleeptime = (nsleeptime > sleeptime)? nsleeptime : sleeptime;
param->bandlims[i]->basetime = sec;
param->bandlims[i]->nexttime = msec + nsleeptime + (((uint64_t)nbytesin * 8 * 1000000) / param->bandlims[i]->rate);
}
for(i=0; nbytesout && i<MAXBANDLIMS && param->bandlimsout[i]; i++){
if( !param->bandlimsout[i]->basetime ||
param->bandlimsout[i]->basetime > sec ||
param->bandlimsout[i]->basetime < (sec - 120)
)
{
param->bandlimsout[i]->basetime = sec;
param->bandlimsout[i]->nexttime = 0;
continue;
}
now = (unsigned)((sec - param->bandlimsout[i]->basetime) * 1000000) + msec;
nsleeptime = (param->bandlimsout[i]->nexttime > now)?
param->bandlimsout[i]->nexttime - now : 0;
sleeptime = (nsleeptime > sleeptime)? nsleeptime : sleeptime;
param->bandlimsout[i]->basetime = sec;
param->bandlimsout[i]->nexttime = msec + nsleeptime + ((nbytesout > 512)? ((nbytesout+32)/64)*((64*8*1000000)/param->bandlimsout[i]->rate) : ((nbytesout+1)* (8*1000000))/param->bandlimsout[i]->rate);
}
pthread_mutex_unlock(&bandlim_mutex);
return sleeptime/1000;
}
void trafcountfunc(struct clientparam *param){
struct trafcount * tc;
int countout = 0;
pthread_mutex_lock(&tc_mutex);
for(tc = conf.trafcounter; tc; tc = tc->next) {
if(ACLmatches(tc->ace, param)){
if(tc->ace->action == NOCOUNTIN) {
countout = 1;
break;
}
if(tc->ace->action == NOCOUNTALL) break;
if(tc->ace->action != COUNTIN && tc->ace->action != COUNTALL) {
countout = 1;
continue;
}
tc->traf64 += param->statssrv64;
tc->updated = conf.time;
}
}
if(countout) for(tc = conf.trafcounter; tc; tc = tc->next) {
if(ACLmatches(tc->ace, param)){
if(tc->ace->action == NOCOUNTOUT || tc->ace->action == NOCOUNTALL) break;
if(tc->ace->action != COUNTOUT && tc->ace->action != COUNTALL ) {
continue;
}
tc->traf64 += param->statscli64;
tc->updated = conf.time;
}
}
pthread_mutex_unlock(&tc_mutex);
}
int alwaysauth(struct clientparam * param){ int alwaysauth(struct clientparam * param){
int res; int res;
@ -689,13 +21,13 @@ int alwaysauth(struct clientparam * param){
res = doconnect(param); res = doconnect(param);
if(!res){ if(!res){
if(conf.bandlimfunc && (conf.bandlimiter||conf.bandlimiterout)){ if(conf.bandlimfunc && (conf.bandlimiter||conf.bandlimiterout)){
pthread_mutex_lock(&bandlim_mutex); _3proxy_mutex_lock(&bandlim_mutex);
initbandlims(param); initbandlims(param);
pthread_mutex_unlock(&bandlim_mutex); _3proxy_mutex_unlock(&bandlim_mutex);
} }
if(conf.trafcountfunc && conf.trafcounter) { if(conf.trafcountfunc && conf.trafcounter) {
pthread_mutex_lock(&tc_mutex); _3proxy_mutex_lock(&tc_mutex);
for(tc = conf.trafcounter; tc; tc = tc->next) { for(tc = conf.trafcounter; tc; tc = tc->next) {
if(tc->disabled) continue; if(tc->disabled) continue;
if(ACLmatches(tc->ace, param)){ if(ACLmatches(tc->ace, param)){
@ -709,7 +41,7 @@ int alwaysauth(struct clientparam * param){
if(tc->ace->action != COUNTALL) continue; if(tc->ace->action != COUNTALL) continue;
} }
if(tc->traflim64 <= tc->traf64) { if(tc->traflim64 <= tc->traf64) {
pthread_mutex_unlock(&tc_mutex); _3proxy_mutex_unlock(&tc_mutex);
return 10; return 10;
} }
param->trafcountfunc = conf.trafcountfunc; param->trafcountfunc = conf.trafcountfunc;
@ -724,57 +56,19 @@ int alwaysauth(struct clientparam * param){
continue; continue;
} }
if(tc->traflim64 <= tc->traf64) { if(tc->traflim64 <= tc->traf64) {
pthread_mutex_unlock(&tc_mutex); _3proxy_mutex_unlock(&tc_mutex);
return 10; return 10;
} }
param->trafcountfunc = conf.trafcountfunc; param->trafcountfunc = conf.trafcountfunc;
param->maxtrafout64 = tc->traflim64 - tc->traf64; param->maxtrafout64 = tc->traflim64 - tc->traf64;
} }
} }
pthread_mutex_unlock(&tc_mutex); _3proxy_mutex_unlock(&tc_mutex);
} }
} }
return res; return res;
} }
int checkACL(struct clientparam * param){
struct ace* acentry;
if(!param->srv->acl) {
return 0;
}
for(acentry = param->srv->acl; acentry; acentry = acentry->next) {
if(ACLmatches(acentry, param)) {
param->nolog = acentry->nolog;
param->weight = acentry->weight;
if(acentry->action == 2) {
struct ace dup;
int res=60,i=0;
if(param->operation < 256 && !(param->operation & CONNECT)){
continue;
}
if(param->redirected && acentry->chains && SAISNULL(&acentry->chains->addr) && !*SAPORT(&acentry->chains->addr)) {
continue;
}
if(param->remsock != INVALID_SOCKET) {
return 0;
}
for(; i < conf.parentretries; i++){
dup = *acentry;
res = handleredirect(param, &dup);
if(!res) break;
if(param->remsock != INVALID_SOCKET) param->srv->so._closesocket(param->sostate, param->remsock);
param->remsock = INVALID_SOCKET;
}
return res;
}
return acentry->action;
}
}
return 3;
}
int cacheauth(struct clientparam * param){ int cacheauth(struct clientparam * param){
struct authcache ac; struct authcache ac;
uint32_t ttl; uint32_t ttl;
@ -799,8 +93,8 @@ int cacheauth(struct clientparam * param){
} }
if(!(conf.authcachetype&2) && *ac.username){ if(!(conf.authcachetype&2) && *ac.username){
if(param->username) myfree(param->username); if(param->username) free(param->username);
param->username = (unsigned char *)mystrdup((char *)ac.username); param->username = (unsigned char *)strdup((char *)ac.username);
} }
if((conf.authcachetype & 32)){ if((conf.authcachetype & 32)){
memset(&param->sinsl, 0, sizeof(param->sinsl)); memset(&param->sinsl, 0, sizeof(param->sinsl));
@ -825,7 +119,10 @@ int doauth(struct clientparam * param){
if(conf.authcachetype && authfuncs->authenticate && authfuncs->authenticate != cacheauth && param->username && (!(conf.authcachetype&4) || (!param->pwtype && param->password))){ if(conf.authcachetype && authfuncs->authenticate && authfuncs->authenticate != cacheauth && param->username && (!(conf.authcachetype&4) || (!param->pwtype && param->password))){
struct authcache ac={.username=""}; struct authcache ac={.username=""};
if(param->username) strncpy((char *)ac.username, (char *)param->username, 64); if(param->username) {
strncpy((char *)ac.username, (char *)param->username, 64);
ac.username[63] = 0;
}
if(*SAFAMILY(&param->sincr) == AF_INET if(*SAFAMILY(&param->sincr) == AF_INET
#ifndef NOIPv6 #ifndef NOIPv6
|| *SAFAMILY(&param->sincr) == AF_INET6 || *SAFAMILY(&param->sincr) == AF_INET6
@ -919,46 +216,46 @@ int dnsauth(struct clientparam * param){
} }
int strongauth(struct clientparam * param){ int strongauth(struct clientparam * param){
struct passwords * pwl; static char dummy;
unsigned char buf[256]; unsigned char buf[256];
char pass[256] = {0};
if (!param->username) return 4;
if(!param->username) return 4; if (!param->pwtype && param->password) {
pthread_mutex_lock(&pwl_mutex); if (pwl_table.ihashtable && hashresolv(&pwl_table, param->username, pass, NULL)) {
for(pwl = conf.pwl; pwl; pwl=pwl->next){ switch(pass[0]){
if(!strcmp((char *)pwl->user, (char *)param->username)) switch(pwl->pwtype) { case CL: {
case CL: int pwlen = strlen((char *)param->password);
if(!pwl->password || !*pwl->password){ if(pwlen > 255) pwlen = 255;
break; if((unsigned)pwlen < pwl_table.recsize) {
} if(!strncmp(pass + 1, (char *)param->password, pwl_table.recsize - 1)) return 0;
else if (!param->pwtype && param->password && !strcmp((char *)param->password, (char *)pwl->password)){ } else {
break; blake2b_state S;
} unsigned hashsz;
pthread_mutex_unlock(&pwl_mutex); hashsz = pwl_table.recsize - 1 < 64 ? pwl_table.recsize - 1 : 64;
return 6; memset(buf, 0, pwl_table.recsize - 1);
#ifndef NOCRYPT blake2b_init(&S, hashsz);
case CR: blake2b_update(&S, param->password, pwlen + 1);
if(param->password && !param->pwtype && !strcmp((char *)pwl->password, (char *)mycrypt(param->password, pwl->password,buf))) { blake2b_final(&S, buf, hashsz);
break; if(!memcmp(pass + 1, buf, pwl_table.recsize - 1)) return 0;
} }
pthread_mutex_unlock(&pwl_mutex); return 6;
return 7; }
case NT: case CR:
if(param->password && !param->pwtype && !memcmp(pwl->password, ntpwdhash(buf,param->password, 1), 32)) { if (mycrypt(param->password, (unsigned char *)pass + 1, buf) &&
break; !strcmp(pass + 1, (char *)buf))
} return 0;
pthread_mutex_unlock(&pwl_mutex); else return 7;
return 8; #ifdef WITH_SSL
case NT:
if(ntpwdhash(buf, param->password, 1) && !strcmp(pass + 1, (char *)buf)) return 0;
else return 8;
#endif #endif
default: default:
pthread_mutex_unlock(&pwl_mutex); break;
return 999; }
} }
else continue;
pthread_mutex_unlock(&pwl_mutex);
return 0;
} }
pthread_mutex_unlock(&pwl_mutex);
return 5; return 5;
} }

View File

@ -1,6 +1,6 @@
/* /*
3APA3A simplest proxy server 3APA3A simplest proxy server
(c) 2000-2021 by Vladimir Dubrovin <3proxy@3proxy.org> (c) 2000-2026 by Vladimir Dubrovin <vlad@3proxy.org>
please read License Agreement please read License Agreement
@ -8,7 +8,7 @@
#ifndef NORADIUS #ifndef NORADIUS
#include "proxy.h" #include "proxy.h"
#include "libs/md5.h" #include <openssl/evp.h>
#define AUTH_VECTOR_LEN 16 #define AUTH_VECTOR_LEN 16
#define MAX_STRING_LEN 254 #define MAX_STRING_LEN 254
@ -72,6 +72,8 @@
#define PW_ACCT_INPUT_PACKETS 47 #define PW_ACCT_INPUT_PACKETS 47
#define PW_ACCT_OUTPUT_PACKETS 48 #define PW_ACCT_OUTPUT_PACKETS 48
#define PW_ACCT_TERMINATE_CAUSE 49 #define PW_ACCT_TERMINATE_CAUSE 49
#define PW_ACCT_INPUT_GIGAWORDS 52
#define PW_ACCT_OUTPUT_GIGAWORDS 53
#define PW_EVENT_TIMESTAMP 55 #define PW_EVENT_TIMESTAMP 55
@ -166,7 +168,7 @@ static int ntry = 0;
int nradservers = 0; int nradservers = 0;
char radiussecret[64]=""; char radiussecret[64]="";
pthread_mutex_t rad_mutex; _3proxy_mutex_t rad_mutex;
void md5_calc(unsigned char *output, unsigned char *input, void md5_calc(unsigned char *output, unsigned char *input,
unsigned int inputlen); unsigned int inputlen);
@ -183,14 +185,25 @@ char *strNcpy(char *dest, const char *src, int n)
return dest; return dest;
} }
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
extern EVP_MD *md4_hash;
extern EVP_MD *md5_hash;
#endif
void md5_calc(unsigned char *output, unsigned char *input, void md5_calc(unsigned char *output, unsigned char *input,
unsigned int inlen) unsigned int inlen)
{ {
MD5_CTX context; EVP_MD_CTX *ctx = EVP_MD_CTX_new();
unsigned int len = 0;
MD5Init(&context); #if OPENSSL_VERSION_NUMBER >= 0x30000000L
MD5Update(&context, input, inlen); EVP_DigestInit_ex(ctx, md5_hash, NULL);
MD5Final(output, &context); #else
EVP_DigestInit_ex(ctx, EVP_md5(), NULL);
#endif
EVP_DigestUpdate(ctx, input, inlen);
EVP_DigestFinal_ex(ctx, output, &len);
EVP_MD_CTX_free(ctx);
} }
@ -268,7 +281,7 @@ void random_vector(uint8_t *vector, struct clientparam *param)
ntry = (int)basetime; ntry = (int)basetime;
for (i = 0; i < (int)sizeof(random_vector_pool); i++) { for (i = 0; i < (int)sizeof(random_vector_pool); i++) {
random_vector_pool[i] += myrand((void *) &param->msec_start, sizeof(param->msec_start)) & 0xff; random_vector_pool[i] += myrand() & 0xff;
} }
did_random = 1; did_random = 1;
@ -327,11 +340,11 @@ int radsend(struct clientparam * param, int auth, int stop){
memset(&packet, 0, sizeof(packet)); memset(&packet, 0, sizeof(packet));
pthread_mutex_lock(&rad_mutex); _3proxy_mutex_lock(&rad_mutex);
if(auth)random_vector(packet.vector, param); if(auth)random_vector(packet.vector, param);
id = ((ntry++) & 0xff); id = ((ntry++) & 0xff);
pthread_mutex_unlock(&rad_mutex); _3proxy_mutex_unlock(&rad_mutex);
packet.code = auth?PW_AUTHENTICATION_REQUEST:PW_ACCOUNTING_REQUEST; packet.code = auth?PW_AUTHENTICATION_REQUEST:PW_ACCOUNTING_REQUEST;
packet.id=id; packet.id=id;
@ -364,7 +377,7 @@ int radsend(struct clientparam * param, int auth, int stop){
/* NAS-Port */ /* NAS-Port */
*ptr++ = PW_NAS_PORT_ID; *ptr++ = PW_NAS_PORT_ID;
*ptr++ = 6; *ptr++ = 6;
(*(uint32_t *)ptr)=htonl((uint32_t)ntohs((*SAPORT(&param->srv->intsa)))); (*(uint32_t *)ptr)=htonl(param->srv?(uint32_t)ntohs((*SAPORT(&param->srv->intsa))):0);
ptr+=4; ptr+=4;
total_length+=6; total_length+=6;
@ -468,12 +481,28 @@ int radsend(struct clientparam * param, int auth, int stop){
(*(uint32_t *)ptr)=htonl((uint32_t)param->statssrv64); (*(uint32_t *)ptr)=htonl((uint32_t)param->statssrv64);
ptr+=4; ptr+=4;
total_length+=6; total_length+=6;
/* Acct-Input-Gigawords */
if(param->statssrv64 > 0xFFFFFFFFULL){
*ptr++ = PW_ACCT_INPUT_GIGAWORDS;
*ptr++ = 6;
(*(uint32_t *)ptr)=htonl((uint32_t)(param->statssrv64 >> 32));
ptr+=4;
total_length+=6;
}
/* Acct-Output-Octets */ /* Acct-Output-Octets */
*ptr++ = PW_ACCT_OUTPUT_OCTETS; *ptr++ = PW_ACCT_OUTPUT_OCTETS;
*ptr++ = 6; *ptr++ = 6;
(*(uint32_t *)ptr)=htonl((uint32_t)param->statscli64); (*(uint32_t *)ptr)=htonl((uint32_t)param->statscli64);
ptr+=4; ptr+=4;
total_length+=6; total_length+=6;
/* Acct-Output-Gigawords */
if(param->statscli64 > 0xFFFFFFFFULL){
*ptr++ = PW_ACCT_OUTPUT_GIGAWORDS;
*ptr++ = 6;
(*(uint32_t *)ptr)=htonl((uint32_t)(param->statscli64 >> 32));
ptr+=4;
total_length+=6;
}
/* Acct-Input-Packets */ /* Acct-Input-Packets */
*ptr++ = PW_ACCT_INPUT_PACKETS; *ptr++ = PW_ACCT_INPUT_PACKETS;
*ptr++ = 6; *ptr++ = 6;

View File

@ -1,6 +1,6 @@
/* /*
3APA3A simplest proxy server 3APA3A simplest proxy server
(c) 2002-2021 by Vladimir Dubrovin <3proxy@3proxy.org> (c) 2002-2026 by Vladimir Dubrovin <vlad@3proxy.org>
please read License Agreement please read License Agreement
@ -13,7 +13,7 @@ void * autochild(struct clientparam* param) {
int len; int len;
if(!param->clibuf){ if(!param->clibuf){
if(!(param->clibuf = myalloc(SRVBUFSIZE))) return 0; if(!(param->clibuf = malloc(SRVBUFSIZE))) return 0;
param->clibufsize = SRVBUFSIZE; param->clibufsize = SRVBUFSIZE;
param->clioffset = param->cliinbuf = 0; param->clioffset = param->cliinbuf = 0;
} }

View File

@ -1,5 +1,5 @@
/* /*
(c) 2002-2021 by Vladimir Dubrovin <3proxy@3proxy.org> (c) 2002-2026 by Vladimir Dubrovin <vlad@3proxy.org>
please read License Agreement please read License Agreement

View File

@ -1,6 +1,6 @@
/* /*
3APA3A simplest proxy server 3APA3A simplest proxy server
(c) 2002-2021 by Vladimir Dubrovin <3proxy@3proxy.org> (c) 2002-2026 by Vladimir Dubrovin <vlad@3proxy.org>
please read License Agreement please read License Agreement
@ -13,7 +13,25 @@
char * copyright = COPYRIGHT; char * copyright = COPYRIGHT;
int randomizer = 1; #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
# define MYRAND_ARC4RANDOM 1
#elif defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 36)))
# define MYRAND_ARC4RANDOM 1
#elif defined(__linux__)
# define MYRAND_GETRANDOM 1
# include <sys/random.h>
#elif defined(_WIN32)
# if defined(__WATCOMC__)
# define MYRAND_CRYPTGENRANDOM 1
# include <wincrypt.h>
# else
# define MYRAND_BCRYPTGENRANDOM 1
# include <bcrypt.h>
# pragma comment(lib, "bcrypt.lib")
# endif
#else
# define MYRAND_FALLBACK 1
#endif
@ -22,10 +40,15 @@ int randomizer = 1;
void daemonize(void){ void daemonize(void){
if(fork() > 0) { pid_t pid = fork();
if(pid > 0) {
usleep(SLEEPTIME); usleep(SLEEPTIME);
_exit(0); _exit(0);
} }
if(pid < 0) {
perror("fork()");
return;
}
setsid(); setsid();
} }
@ -33,35 +56,6 @@ int randomizer = 1;
unsigned char **stringtable = NULL; unsigned char **stringtable = NULL;
#ifdef WITH_LINUX_FUTEX
int sys_futex(void *addr1, int op, int val1, struct timespec *timeout, void *addr2, int val3)
{
return syscall(SYS_futex, addr1, op, val1, timeout, addr2, val3);
}
int mutex_lock(int *val)
{
int c;
if ((c = __sync_val_compare_and_swap(val, 0, 1)) != 0)
do {
if(c == 2 || __sync_val_compare_and_swap(val, 1, 2) != 0)
sys_futex(val, FUTEX_WAIT_PRIVATE, 2, NULL, NULL, 0);
} while ((c = __sync_val_compare_and_swap(val, 0, 2)) != 0);
return 0;
}
int mutex_unlock(int *val)
{
if(__sync_fetch_and_sub (val, 1) != 1){
*val = 0;
sys_futex(val, FUTEX_WAKE_PRIVATE, 1, NULL, NULL, 0);
}
return 0;
}
#endif
#ifdef WITH_UN #ifdef WITH_UN
void make_un(const unsigned char *path, struct sockaddr_un * sun){ void make_un(const unsigned char *path, struct sockaddr_un * sun){
memset(sun, 0, sizeof(*sun)); memset(sun, 0, sizeof(*sun));
@ -139,7 +133,11 @@ int timeouts[12] = {
}; };
struct extparam conf = { struct extparam conf = {
.threadinit = {0, 0}, #ifdef _WIN32
.threadinit = NULL,
#else
.threadinit = 0,
#endif
.timeouts = timeouts, .timeouts = timeouts,
.acl = NULL, .acl = NULL,
.conffile = NULL, .conffile = NULL,
@ -208,18 +206,31 @@ int numservers=0;
char* NULLADDR="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; char* NULLADDR="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
int myrand(void * entropy, int len){ uint32_t myrand(void){
int i; #if defined(MYRAND_ARC4RANDOM)
uint16_t init; return arc4random();
#elif defined(MYRAND_GETRANDOM)
init = randomizer; uint32_t r = 0;
for(i=0; i < len/2; i++){ ssize_t n;
init ^= ((uint16_t *)entropy)[i]; do {
n = getrandom(&r, sizeof(r), 0);
} while(n < 0 && errno == EINTR);
return r;
#elif defined(MYRAND_BCRYPTGENRANDOM)
uint32_t r = 0;
BCryptGenRandom(NULL, (PUCHAR)&r, sizeof(r), BCRYPT_USE_SYSTEM_PREFERRED_RNG);
return r;
#elif defined(MYRAND_CRYPTGENRANDOM)
uint32_t r = 0;
HCRYPTPROV prov;
if(CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT|CRYPT_SILENT)){
CryptGenRandom(prov, sizeof(r), (BYTE *)&r);
CryptReleaseContext(prov, 0);
} }
srand(rand()+init); return r;
randomizer = rand(); #else
return rand(); return ((uint32_t)rand() << 16) ^ (uint32_t)rand();
#endif
} }
#ifndef WITH_POLL #ifndef WITH_POLL
@ -244,6 +255,9 @@ int
FD_ZERO(&writefd); FD_ZERO(&writefd);
FD_ZERO(&oobfd); FD_ZERO(&oobfd);
for(i=0; i<nfds; i++){ for(i=0; i<nfds; i++){
#ifndef _WIN32
if(fds[i].fd >= FD_SETSIZE) continue;
#endif
if((fds[i].events&POLLIN))FD_SET(fds[i].fd, &readfd); if((fds[i].events&POLLIN))FD_SET(fds[i].fd, &readfd);
if((fds[i].events&POLLOUT))FD_SET(fds[i].fd, &writefd); if((fds[i].events&POLLOUT))FD_SET(fds[i].fd, &writefd);
if((fds[i].events&POLLPRI))FD_SET(fds[i].fd, &oobfd); if((fds[i].events&POLLPRI))FD_SET(fds[i].fd, &oobfd);
@ -252,6 +266,9 @@ int
} }
if((num = select(((int)(maxfd))+1, &readfd, &writefd, &oobfd, &tv)) < 1) return num; if((num = select(((int)(maxfd))+1, &readfd, &writefd, &oobfd, &tv)) < 1) return num;
for(i=0; i<nfds; i++){ for(i=0; i<nfds; i++){
#ifndef _WIN32
if(fds[i].fd >= FD_SETSIZE) continue;
#endif
if(FD_ISSET(fds[i].fd, &readfd)) fds[i].revents |= POLLIN; if(FD_ISSET(fds[i].fd, &readfd)) fds[i].revents |= POLLIN;
if(FD_ISSET(fds[i].fd, &writefd)) fds[i].revents |= POLLOUT; if(FD_ISSET(fds[i].fd, &writefd)) fds[i].revents |= POLLOUT;
if(FD_ISSET(fds[i].fd, &oobfd)) fds[i].revents |= POLLPRI; if(FD_ISSET(fds[i].fd, &oobfd)) fds[i].revents |= POLLPRI;
@ -481,8 +498,8 @@ int parsehostname(char *hostname, struct clientparam *param, uint16_t port){
*se = 0; *se = 0;
} }
if(hostname != (char *)param->hostname){ if(hostname != (char *)param->hostname){
if(param->hostname) myfree(param->hostname); if(param->hostname) free(param->hostname);
param->hostname = (unsigned char *)mystrdup(hostname + (se!=0)); param->hostname = (unsigned char *)strdup(hostname + (se!=0));
} }
if(sp){ if(sp){
port = atoi(sp+1); port = atoi(sp+1);
@ -504,12 +521,12 @@ int parseusername(char *username, struct clientparam *param, int extpasswd){
*se = 0; *se = 0;
if(sp) *sp = 0; if(sp) *sp = 0;
if(*(sb+1)) { if(*(sb+1)) {
if(param->password) myfree(param->password); if(param->password) free(param->password);
param->password = (unsigned char *)mystrdup(sb+1); param->password = (unsigned char *)strdup(sb+1);
} }
if(*username) { if(*username) {
if(param->username) myfree(param->username); if(param->username) free(param->username);
param->username = (unsigned char *)mystrdup(username); param->username = (unsigned char *)strdup(username);
} }
username = se+1; username = se+1;
} }
@ -517,12 +534,12 @@ int parseusername(char *username, struct clientparam *param, int extpasswd){
if(!sp) sp = strchr(username, ':'); if(!sp) sp = strchr(username, ':');
if(sp){ if(sp){
*sp = 0; *sp = 0;
if(param->extpassword) myfree(param->extpassword); if(param->extpassword) free(param->extpassword);
param->extpassword = (unsigned char *) mystrdup(sp+1); param->extpassword = (unsigned char *) strdup(sp+1);
} }
} }
if(param->extusername) myfree(param->extusername); if(param->extusername) free(param->extusername);
param->extusername = (unsigned char *)mystrdup(username); param->extusername = (unsigned char *)strdup(username);
if(sb) *sb = ':'; if(sb) *sb = ':';
if(se) *se = ':'; if(se) *se = ':';
if(sp) *sp = ':'; if(sp) *sp = ':';
@ -575,9 +592,10 @@ int doconnect(struct clientparam * param){
if (*SAFAMILY(&param->sincl) == *SAFAMILY(&param->req) && !memcmp(SAADDR(&param->sincl), SAADDR(&param->req), SAADDRLEN(&param->req)) && if (*SAFAMILY(&param->sincl) == *SAFAMILY(&param->req) && !memcmp(SAADDR(&param->sincl), SAADDR(&param->req), SAADDRLEN(&param->req)) &&
*SAPORT(&param->sincl) == *SAPORT(&param->req)) return 519; *SAPORT(&param->sincl) == *SAPORT(&param->req)) return 519;
if (param->operation == ADMIN || param->operation == DNSRESOLVE || param->operation == BIND || param->operation == UDPASSOC) if (param->operation == ADMIN || (( param->operation == DNSRESOLVE || param->operation == BIND || param->operation == UDPASSOC) && !param->redirected))
return 0; return 0;
if (param->remsock != INVALID_SOCKET){ if (param->remsock != INVALID_SOCKET){
if(param->operation == UDPASSOC) return 0;
size = sizeof(param->sinsr); size = sizeof(param->sinsr);
if(param->srv->so._getpeername(param->sostate, param->remsock, (struct sockaddr *)&param->sinsr, &size)==-1) {return (14);} if(param->srv->so._getpeername(param->sostate, param->remsock, (struct sockaddr *)&param->sinsr, &size)==-1) {return (14);}
} }
@ -650,7 +668,7 @@ int doconnect(struct clientparam * param){
return 12; return 12;
} }
if(param->operation >= 256 || (param->operation & CONNECT)){ if(param->operation >= 256 || (param->operation & CONNECT) || param->redirected){
if(connectwithpoll(param, param->remsock,(struct sockaddr *)&param->sinsr,SASIZE(&param->sinsr),conf.timeouts[CONNECT_TO])) { if(connectwithpoll(param, param->remsock,(struct sockaddr *)&param->sinsr,SASIZE(&param->sinsr),conf.timeouts[CONNECT_TO])) {
return 13; return 13;
} }
@ -664,7 +682,6 @@ int doconnect(struct clientparam * param){
action = handleconnectflt(param); action = handleconnectflt(param);
if(action != PASS) return 19; if(action != PASS) return 19;
} }
return 0; return 0;
} }
@ -680,7 +697,7 @@ int scanaddr(const unsigned char *s, uint32_t * ip, uint32_t * mask) {
RESOLVFUNC resolvfunc = NULL; RESOLVFUNC resolvfunc = NULL;
#ifndef _WIN32 #ifndef _WIN32
pthread_mutex_t gethostbyname_mutex; _3proxy_mutex_t gethostbyname_mutex;
int ghbn_init = 0; int ghbn_init = 0;
#endif #endif
@ -736,10 +753,10 @@ uint32_t getip(unsigned char *name){
#ifndef NOSTDRESOLVE #ifndef NOSTDRESOLVE
#if !defined(_WIN32) && !defined(GETHOSTBYNAME_R) #if !defined(_WIN32) && !defined(GETHOSTBYNAME_R)
if(!ghbn_init){ if(!ghbn_init){
pthread_mutex_init(&gethostbyname_mutex, NULL); _3proxy_mutex_init(&gethostbyname_mutex);
ghbn_init++; ghbn_init++;
} }
pthread_mutex_lock(&gethostbyname_mutex); _3proxy_mutex_lock(&gethostbyname_mutex);
#endif #endif
hp=gethostbyname((char *)name); hp=gethostbyname((char *)name);
if (!hp && conf.demanddialprog) { if (!hp && conf.demanddialprog) {
@ -748,7 +765,7 @@ uint32_t getip(unsigned char *name){
} }
retval = hp?*(uint32_t *)hp->h_addr:0; retval = hp?*(uint32_t *)hp->h_addr:0;
#if !defined(_WIN32) && !defined(GETHOSTBYNAME_R) #if !defined(_WIN32) && !defined(GETHOSTBYNAME_R)
pthread_mutex_unlock(&gethostbyname_mutex); _3proxy_mutex_unlock(&gethostbyname_mutex);
#endif #endif
#ifdef GETHOSTBYNAME_R #ifdef GETHOSTBYNAME_R
#undef gethostbyname #undef gethostbyname
@ -795,7 +812,9 @@ int afdetect(unsigned char *name){
uint32_t getip46(int family, unsigned char *name, struct sockaddr *sa){ uint32_t getip46(int family, unsigned char *name, struct sockaddr *sa){
#ifndef NOIPV6 #ifndef NOIPV6
int detect; int detect;
#ifndef NOSTDRESOLVE
struct addrinfo *ai, hint; struct addrinfo *ai, hint;
#endif
RESOLVFUNC tmpresolv; RESOLVFUNC tmpresolv;
if(!sa) return 0; if(!sa) return 0;
@ -815,7 +834,6 @@ uint32_t getip46(int family, unsigned char *name, struct sockaddr *sa){
return inet_pton(*SAFAMILY(sa), (char *)name, SAADDR(sa))>0? *SAFAMILY(sa) : 0; return inet_pton(*SAFAMILY(sa), (char *)name, SAADDR(sa))>0? *SAFAMILY(sa) : 0;
} }
if((tmpresolv = resolvfunc)){ if((tmpresolv = resolvfunc)){
int f = (family == 6 || family == 64)?AF_INET6:AF_INET; int f = (family == 6 || family == 64)?AF_INET6:AF_INET;
*SAFAMILY(sa) = f; *SAFAMILY(sa) = f;
@ -826,6 +844,7 @@ uint32_t getip46(int family, unsigned char *name, struct sockaddr *sa){
if(tmpresolv(f, name, SAADDR(sa))) return f; if(tmpresolv(f, name, SAADDR(sa))) return f;
return 0; return 0;
} }
#ifndef NOSTDRESOLVE
memset(&hint, 0, sizeof(hint)); memset(&hint, 0, sizeof(hint));
hint.ai_family = (family == 6 || family == 64)?AF_INET6:AF_INET; hint.ai_family = (family == 6 || family == 64)?AF_INET6:AF_INET;
if (getaddrinfo((char *)name, NULL, &hint, &ai)) { if (getaddrinfo((char *)name, NULL, &hint, &ai)) {
@ -844,6 +863,7 @@ uint32_t getip46(int family, unsigned char *name, struct sockaddr *sa){
} }
freeaddrinfo(ai); freeaddrinfo(ai);
} }
#endif
return 0; return 0;
#endif #endif
} }

View File

@ -1,12 +1,19 @@
/* /*
3APA3A simplest proxy server 3APA3A simplest proxy server
(c) 2002-2021 by Vladimir Dubrovin <3proxy@3proxy.org> (c) 2002-2026 by Vladimir Dubrovin <vlad@3proxy.org>
please read License Agreement please read License Agreement
*/ */
#include "proxy.h" #include "proxy.h"
#include "libs/blake2.h"
#ifdef WITH_SSL
void ssl_install(void);
#endif
#ifdef WITH_PCRE
void pcre_install(void);
#endif
#ifndef _WIN32 #ifndef _WIN32
#include <sys/resource.h> #include <sys/resource.h>
#include <pwd.h> #include <pwd.h>
@ -20,12 +27,10 @@
#define DEFAULTCONFIG conf.stringtable[25] #define DEFAULTCONFIG conf.stringtable[25]
#endif #endif
pthread_mutex_t bandlim_mutex; _3proxy_mutex_t bandlim_mutex;
pthread_mutex_t connlim_mutex; _3proxy_mutex_t connlim_mutex;
pthread_mutex_t tc_mutex; _3proxy_mutex_t tc_mutex;
pthread_mutex_t pwl_mutex; _3proxy_mutex_t config_mutex;
pthread_mutex_t hash_mutex;
pthread_mutex_t config_mutex;
int haveerror = 0; int haveerror = 0;
int linenum = 0; int linenum = 0;
@ -103,6 +108,14 @@ int getrotate(char c){
unsigned char * dologname (unsigned char *buf, unsigned char *name, const unsigned char *ext, ROTATION lt, time_t t) { unsigned char * dologname (unsigned char *buf, unsigned char *name, const unsigned char *ext, ROTATION lt, time_t t) {
struct tm *ts; struct tm *ts;
static const char * const rot_fmt[] = {
[NONE] = "%s",
[ANNUALLY] = "%s.%04d",
[MONTHLY] = "%s.%04d.%02d",
[DAILY] = "%s.%04d.%02d.%02d",
[HOURLY] = "%s.%04d.%02d.%02d-%02d",
[MINUTELY] = "%s.%04d.%02d.%02d-%02d.%02d",
};
ts = localtime(&t); ts = localtime(&t);
if(strlen((char *)name) >= 4096){ if(strlen((char *)name) >= 4096){
@ -110,37 +123,15 @@ unsigned char * dologname (unsigned char *buf, unsigned char *name, const unsign
return buf; return buf;
} }
if(strchr((char *)name, '%')){ if(strchr((char *)name, '%')){
struct clientparam fakecli; dobuf2(NULL, buf, NULL, NULL, ts, (char *)name);
memset(&fakecli, 0, sizeof(fakecli));
dobuf2(&fakecli, buf, NULL, NULL, ts, (char *)name);
} }
else switch(lt){ else if(lt == WEEKLY){
case NONE: t = t - (ts->tm_wday * (60*60*24));
sprintf((char *)buf, "%s", name); ts = localtime(&t);
break; sprintf((char *)buf, "%s.%04d.%02d.%02d", name, ts->tm_year+1900, ts->tm_mon+1, ts->tm_mday);
case ANNUALLY: }
sprintf((char *)buf, "%s.%04d", name, ts->tm_year+1900); else if((unsigned)lt < sizeof(rot_fmt)/sizeof(rot_fmt[0]) && rot_fmt[lt]){
break; sprintf((char *)buf, rot_fmt[lt], name, ts->tm_year+1900, ts->tm_mon+1, ts->tm_mday, ts->tm_hour, ts->tm_min);
case MONTHLY:
sprintf((char *)buf, "%s.%04d.%02d", name, ts->tm_year+1900, ts->tm_mon+1);
break;
case WEEKLY:
t = t - (ts->tm_wday * (60*60*24));
ts = localtime(&t);
sprintf((char *)buf, "%s.%04d.%02d.%02d", name, ts->tm_year+1900, ts->tm_mon+1, ts->tm_mday);
break;
case DAILY:
sprintf((char *)buf, "%s.%04d.%02d.%02d", name, ts->tm_year+1900, ts->tm_mon+1, ts->tm_mday);
break;
case HOURLY:
sprintf((char *)buf, "%s.%04d.%02d.%02d-%02d", name, ts->tm_year+1900, ts->tm_mon+1, ts->tm_mday, ts->tm_hour);
break;
case MINUTELY:
sprintf((char *)buf, "%s.%04d.%02d.%02d-%02d.%02d", name, ts->tm_year+1900, ts->tm_mon+1, ts->tm_mday, ts->tm_hour, ts->tm_min);
break;
default:
break;
} }
if(ext){ if(ext){
strcat((char *)buf, "."); strcat((char *)buf, ".");
@ -153,10 +144,9 @@ int start_proxy_thread(struct child * chp){
pthread_t thread; pthread_t thread;
#ifdef _WIN32 #ifdef _WIN32
HANDLE h; HANDLE h;
DWORD num;
#endif #endif
char r[1];
_3proxy_sem_lock(conf.threadinit);
#ifdef _WIN32 #ifdef _WIN32
#ifndef _WINCE #ifndef _WINCE
h = (HANDLE)_beginthreadex((LPSECURITY_ATTRIBUTES )NULL, 16384+conf.stacksize, (void *)startsrv, (void *) chp, (DWORD)0, &thread); h = (HANDLE)_beginthreadex((LPSECURITY_ATTRIBUTES )NULL, 16384+conf.stacksize, (void *)startsrv, (void *) chp, (DWORD)0, &thread);
@ -171,14 +161,8 @@ int start_proxy_thread(struct child * chp){
pthread_create(&thread, &pa, startsrv, (void *)chp); pthread_create(&thread, &pa, startsrv, (void *)chp);
pthread_attr_destroy(&pa); pthread_attr_destroy(&pa);
#endif #endif
#ifdef _WIN32 _3proxy_sem_lock(conf.threadinit);
ReadFile(conf.threadinit[0], r, 1, &num, NULL); _3proxy_sem_unlock(conf.threadinit);
#else
while(read(conf.threadinit[0], r, 1) !=1) if(errno != EINTR) {
fprintf(stderr, "pipe failed\n");
return 40;
}
#endif
if(haveerror) { if(haveerror) {
fprintf(stderr, "Service not started on line: %d%s\n", linenum, haveerror == 2? ": insufficient memory":""); fprintf(stderr, "Service not started on line: %d%s\n", linenum, haveerror == 2? ": insufficient memory":"");
return(40); return(40);
@ -196,7 +180,6 @@ static int h_proxy(int argc, unsigned char ** argv){
childdef.port = 3128; childdef.port = 3128;
childdef.isudp = 0; childdef.isudp = 0;
childdef.service = S_PROXY; childdef.service = S_PROXY;
childdef.helpmessage = " -n - no NTLM support\n";
#ifdef NOIPV6 #ifdef NOIPV6
if(!resolvfunc || (resolvfunc == myresolver && !dns_table.poolsize)){ if(!resolvfunc || (resolvfunc == myresolver && !dns_table.poolsize)){
fprintf(stderr, "[line %d] Warning: no nserver/nscache configured, proxy may run very slow\n", linenum); fprintf(stderr, "[line %d] Warning: no nserver/nscache configured, proxy may run very slow\n", linenum);
@ -229,7 +212,6 @@ static int h_proxy(int argc, unsigned char ** argv){
childdef.port = 1080; childdef.port = 1080;
childdef.isudp = 0; childdef.isudp = 0;
childdef.service = S_SOCKS; childdef.service = S_SOCKS;
childdef.helpmessage = " -n - no NTLM support\n";
#ifdef NOIPV6 #ifdef NOIPV6
if(!resolvfunc || (resolvfunc == myresolver && !dns_table.poolsize)){ if(!resolvfunc || (resolvfunc == myresolver && !dns_table.poolsize)){
fprintf(stderr, "[line %d] Warning: no nserver/nscache configured, socks may run very slow\n", linenum); fprintf(stderr, "[line %d] Warning: no nserver/nscache configured, socks may run very slow\n", linenum);
@ -322,7 +304,7 @@ static int h_log(int argc, unsigned char ** argv){
notchanged = 1; notchanged = 1;
} }
if(!notchanged && conf.logtarget){ if(!notchanged && conf.logtarget){
myfree(conf.logtarget); free(conf.logtarget);
conf.logtarget = NULL; conf.logtarget = NULL;
} }
if(argc > 1) { if(argc > 1) {
@ -330,7 +312,7 @@ static int h_log(int argc, unsigned char ** argv){
conf.logfunc = lognone; conf.logfunc = lognone;
return 0; return 0;
} }
if(!notchanged) conf.logtarget = (unsigned char *)mystrdup((char *)argv[1]); if(!notchanged) conf.logtarget = (unsigned char *)strdup((char *)argv[1]);
if(*argv[1]=='@'){ if(*argv[1]=='@'){
#ifndef _WIN32 #ifndef _WIN32
conf.logfunc = logsyslog; conf.logfunc = logsyslog;
@ -338,14 +320,14 @@ static int h_log(int argc, unsigned char ** argv){
openlog((char *)conf.logtarget+1, LOG_PID, LOG_DAEMON); openlog((char *)conf.logtarget+1, LOG_PID, LOG_DAEMON);
#endif #endif
} }
#ifndef NOODBC #ifdef WITH_ODBC
else if(*argv[1]=='&'){ else if(*argv[1]=='&'){
conf.logfunc = logsql; conf.logfunc = logsql;
if(notchanged) return 0; if(notchanged) return 0;
pthread_mutex_lock(&log_mutex); _3proxy_mutex_lock(&log_mutex);
close_sql(); close_sql();
init_sql((char *)argv[1]+1); init_sql((char *)argv[1]+1);
pthread_mutex_unlock(&log_mutex); _3proxy_mutex_unlock(&log_mutex);
} }
#endif #endif
#ifndef NORADIUS #ifndef NORADIUS
@ -360,8 +342,8 @@ static int h_log(int argc, unsigned char ** argv){
conf.logfunc = logstdout; conf.logfunc = logstdout;
if(notchanged) return 0; if(notchanged) return 0;
conf.logtime = time(0); conf.logtime = time(0);
if(conf.logname)myfree(conf.logname); if(conf.logname)free(conf.logname);
conf.logname = (unsigned char *)mystrdup((char *)argv[1]); conf.logname = (unsigned char *)strdup((char *)argv[1]);
if(conf.stdlog) conf.stdlog = freopen((char *)dologname (tmpbuf, conf.logname, NULL, conf.logtype, conf.logtime), "a", conf.stdlog); if(conf.stdlog) conf.stdlog = freopen((char *)dologname (tmpbuf, conf.logname, NULL, conf.logtype, conf.logtime), "a", conf.stdlog);
else conf.stdlog = fopen((char *)dologname (tmpbuf, conf.logname, NULL, conf.logtype, conf.logtime), "a"); else conf.stdlog = fopen((char *)dologname (tmpbuf, conf.logname, NULL, conf.logtype, conf.logtime), "a");
if(!conf.stdlog){ if(!conf.stdlog){
@ -402,8 +384,8 @@ static int h_daemon(int argc, unsigned char **argv){
} }
static int h_config(int argc, unsigned char **argv){ static int h_config(int argc, unsigned char **argv){
if(conf.conffile)myfree(conf.conffile); if(conf.conffile)free(conf.conffile);
conf.conffile = mystrdup((char *)argv[1]); conf.conffile = strdup((char *)argv[1]);
if(!conf.conffile) return 21; if(!conf.conffile) return 21;
return 0; return 0;
} }
@ -425,10 +407,10 @@ static int h_include(int argc, unsigned char **argv){
static int h_archiver(int argc, unsigned char **argv){ static int h_archiver(int argc, unsigned char **argv){
int j; int j;
conf.archiver = myalloc(argc * sizeof(char *)); conf.archiver = malloc(argc * sizeof(char *));
if(conf.archiver) { if(conf.archiver) {
conf.archiverc = argc; conf.archiverc = argc;
for(j = 0; j < conf.archiverc; j++) conf.archiver[j] = (unsigned char *)mystrdup((char *)argv[j]); for(j = 0; j < conf.archiverc; j++) conf.archiver[j] = (unsigned char *)strdup((char *)argv[j]);
} }
return 0; return 0;
} }
@ -446,18 +428,6 @@ static int h_counter(int argc, unsigned char **argv){
fprintf(stderr, "Not a counter file %s, line %d\n", argv[1], linenum); fprintf(stderr, "Not a counter file %s, line %d\n", argv[1], linenum);
return 2; return 2;
} }
#ifdef _TIME64_T_DEFINED
#ifdef _MAX__TIME64_T
#define MAX_COUNTER_TIME (_MAX__TIME64_T)
#elif defined (MAX__TIME64_T)
#define MAX_COUNTER_TIME (MAX__TIME64_T)
#else
#define MAX_COUNTER_TIME (0x793406fff)
#endif
#else
#define MAX_COUNTER_TIME ((sizeof(time_t)>4)?(time_t)0x793406fff:(time_t)0x7fffffff)
#endif
if(ch1.updated < 0 || ch1.updated >= MAX_COUNTER_TIME){ if(ch1.updated < 0 || ch1.updated >= MAX_COUNTER_TIME){
fprintf(stderr, "Invalid or corrupted counter file %s. Use countersutil utility to convert from older version\n", argv[1]); fprintf(stderr, "Invalid or corrupted counter file %s. Use countersutil utility to convert from older version\n", argv[1]);
return 3; return 3;
@ -466,8 +436,8 @@ static int h_counter(int argc, unsigned char **argv){
} }
if(argc >=4) { if(argc >=4) {
conf.countertype = getrotate(*argv[2]); conf.countertype = getrotate(*argv[2]);
if(conf.counterfile) myfree(conf.counterfile); if(conf.counterfile) free(conf.counterfile);
conf.counterfile = mystrdup((char *)argv[3]); conf.counterfile = strdup((char *)argv[3]);
} }
return 0; return 0;
} }
@ -484,8 +454,8 @@ static int h_maxseg(int argc, unsigned char **argv){
static int h_logformat(int argc, unsigned char **argv){ static int h_logformat(int argc, unsigned char **argv){
unsigned char * old = conf.logformat; unsigned char * old = conf.logformat;
conf.logformat = (unsigned char *)mystrdup((char *)argv[1]); conf.logformat = (unsigned char *)strdup((char *)argv[1]);
if(old) myfree(old); if(old) free(old);
return 0; return 0;
} }
@ -514,7 +484,7 @@ static int h_auth(int argc, unsigned char **argv){
for(argc--; argc; argc--){ for(argc--; argc; argc--){
for(au = authfuncs; au; au=au->next){ for(au = authfuncs; au; au=au->next){
if(!strcmp((char *)argv[argc], au->desc)){ if(!strcmp((char *)argv[argc], au->desc)){
newau = myalloc(sizeof(struct auth)); newau = malloc(sizeof(struct auth));
if(!newau) { if(!newau) {
return 21; return 21;
} }
@ -533,46 +503,59 @@ static int h_auth(int argc, unsigned char **argv){
} }
static int h_users(int argc, unsigned char **argv){ static int h_users(int argc, unsigned char **argv){
int j; static char dummy;
unsigned char *arg; int j;
struct passwords *pwl = NULL; unsigned char *arg;
char *pw[2];
for (j = 1; j<argc; j++) { char pass[256];
if(!(pwl = myalloc(sizeof(struct passwords)))) { int l;
return(21);
}
memset(pwl, 0, sizeof(struct passwords));
arg = (unsigned char *)strchr((char *)argv[j], ':');
if(!arg||!arg[1]||!arg[2]||arg[3]!=':') {
pwl->user = (unsigned char *)mystrdup((char *)argv[j]);
pwl->pwtype = SYS;
}
else {
*arg = 0;
pwl->user = (unsigned char *)mystrdup((char *)argv[j]);
if((arg[1] == 'C' && arg[2] == 'L' && (pwl->pwtype = CL)) ||
(arg[1] == 'C' && arg[2] == 'R' && (pwl->pwtype = CR)) ||
(arg[1] == 'N' && arg[2] == 'T' && (pwl->pwtype = NT)) ||
(arg[1] == 'L' && arg[2] == 'M' && (pwl->pwtype = LM))){
pwl->password = (unsigned char *)mystrdup((char *)arg+4);
}
else {
pwl->password = (unsigned char *) mystrdup((char *)arg + 1);
pwl->pwtype = UN;
}
if(!pwl->password) return 3;
}
if(!pwl->user) return 21;
pthread_mutex_lock(&pwl_mutex);
pwl->next = conf.pwl;
conf.pwl = pwl;
pthread_mutex_unlock(&pwl_mutex);
for (j = 1; j < argc; j++) {
arg = (unsigned char *)strchr((char *)argv[j], ':');
if (!arg) continue;
*arg = 0;
pw[0] = (char *)argv[j];
if (!pwl_table.ihashtable && inithashtable(&pwl_table, 16, 32, 1048576))
return 3;
memset(pass, 0, sizeof(pass));
if (arg[1] && arg[2] && arg[3] == ':') {
pw[1] = (char *)(arg + 4);
if (arg[1] == 'N' && arg[2] == 'T') {
#ifdef WITH_SSL
*pass = NT;
#else
continue;
#endif
}
else if (arg[1] == 'C' && arg[2] == 'R') {
*pass = CR;
}
else if (arg[1] == 'C' && arg[2] == 'L') {
*pass = CL;
} else {
continue;
}
} else {
*pass = CL;
pw[1] = (char *)(arg + 1);
}
l = strlen(pw[1]);
if(l > 255) l = 255;
if((unsigned)l >= pwl_table.recsize) {
blake2b_state S;
unsigned hashsz;
if(*pass != CL) continue;
hashsz = pwl_table.recsize - 1 < 64 ? pwl_table.recsize - 1 : 64;
blake2b_init(&S, hashsz);
blake2b_update(&S, pw[1], l + 1);
blake2b_final(&S, pass+1, hashsz);
} else {
memcpy(pass + 1, pw[1], l);
} }
return 0; hashadd(&pwl_table, pw[0], pass, MAX_COUNTER_TIME);
}
return 0;
} }
static int h_maxconn(int argc, unsigned char **argv){ static int h_maxconn(int argc, unsigned char **argv){
@ -597,7 +580,7 @@ static int h_maxconn(int argc, unsigned char **argv){
static int h_backlog(int argc, unsigned char **argv){ static int h_backlog(int argc, unsigned char **argv){
conf.backlog = atoi((char *)argv[1]); conf.backlog = atoi((char *)argv[1]);
if(conf.maxchild < 0) { if(conf.backlog < 0) {
return(1); return(1);
} }
return 0; return 0;
@ -703,8 +686,8 @@ static int h_nsrecord(int argc, unsigned char **argv){
} }
static int h_dialer(int argc, unsigned char **argv){ static int h_dialer(int argc, unsigned char **argv){
if(conf.demanddialprog) myfree(conf.demanddialprog); if(conf.demanddialprog) free(conf.demanddialprog);
conf.demanddialprog = mystrdup((char *)argv[1]); conf.demanddialprog = strdup((char *)argv[1]);
return 0; return 0;
} }
@ -733,14 +716,14 @@ static int h_pidfile(int argc, unsigned char **argv){
static int h_monitor(int argc, unsigned char **argv){ static int h_monitor(int argc, unsigned char **argv){
struct filemon * fm; struct filemon * fm;
fm = myalloc(sizeof (struct filemon)); fm = malloc(sizeof (struct filemon));
if(!fm) return 21; if(!fm) return 21;
if(stat((char *)argv[1], &fm->sb)){ if(stat((char *)argv[1], &fm->sb)){
myfree(fm); free(fm);
fprintf(stderr, "Warning: file %s doesn't exist on line %d\n", argv[1], linenum); fprintf(stderr, "Warning: file %s doesn't exist on line %d\n", argv[1], linenum);
} }
else { else {
fm->path = mystrdup((char *)argv[1]); fm->path = strdup((char *)argv[1]);
if(!fm->path) return 21; if(!fm->path) return 21;
fm->next = conf.fmon; fm->next = conf.fmon;
conf.fmon = fm; conf.fmon = fm;
@ -785,7 +768,7 @@ static int h_parent(int argc, unsigned char **argv){
} }
acl->action = 2; acl->action = 2;
chains = myalloc(sizeof(struct chain)); chains = malloc(sizeof(struct chain));
if(!chains){ if(!chains){
return(21); return(21);
} }
@ -793,6 +776,7 @@ static int h_parent(int argc, unsigned char **argv){
chains->weight = (unsigned)atoi((char *)argv[1]); chains->weight = (unsigned)atoi((char *)argv[1]);
if(chains->weight == 0 || chains->weight >1000) { if(chains->weight == 0 || chains->weight >1000) {
fprintf(stderr, "Chaining error: bad chain weight %u line %d\n", chains->weight, linenum); fprintf(stderr, "Chaining error: bad chain weight %u line %d\n", chains->weight, linenum);
free(chains);
return(3); return(3);
} }
for(i = 0; redirs[i].name ; i++){ for(i = 0; redirs[i].name ; i++){
@ -808,6 +792,7 @@ static int h_parent(int argc, unsigned char **argv){
} }
if(!redirs[i].name) { if(!redirs[i].name) {
fprintf(stderr, "Chaining error: bad chain type (%s)\n", argv[2]); fprintf(stderr, "Chaining error: bad chain type (%s)\n", argv[2]);
free(chains);
return(4); return(4);
} }
#ifdef WITH_UN #ifdef WITH_UN
@ -818,19 +803,25 @@ static int h_parent(int argc, unsigned char **argv){
#endif #endif
cidr = strchr((char *)argv[3], '/'); cidr = strchr((char *)argv[3], '/');
if(cidr) *cidr = 0; if(cidr) *cidr = 0;
if(!getip46(46, argv[3], (struct sockaddr *)&chains->addr)) return (5); if(!getip46(46, argv[3], (struct sockaddr *)&chains->addr)) {
free(chains);
return (5);
}
#ifdef WITH_UN #ifdef WITH_UN
} }
#endif #endif
chains->exthost = (unsigned char *)mystrdup((char *)argv[3]); chains->exthost = (unsigned char *)strdup((char *)argv[3]);
if(!chains->exthost) return 21; if(!chains->exthost) {
free(chains);
return 21;
}
if(cidr){ if(cidr){
*cidr = '/'; *cidr = '/';
chains->cidr = atoi(cidr + 1); chains->cidr = atoi(cidr + 1);
} }
*SAPORT(&chains->addr) = htons((uint16_t)atoi((char *)argv[4])); *SAPORT(&chains->addr) = htons((uint16_t)atoi((char *)argv[4]));
if(argc > 5) chains->extuser = (unsigned char *)mystrdup((char *)argv[5]); if(argc > 5) chains->extuser = (unsigned char *)strdup((char *)argv[5]);
if(argc > 6) chains->extpass = (unsigned char *)mystrdup((char *)argv[6]); if(argc > 6) chains->extpass = (unsigned char *)strdup((char *)argv[6]);
if(!acl->chains) { if(!acl->chains) {
acl->chains = chains; acl->chains = chains;
} }
@ -916,7 +907,7 @@ struct ace * make_ace (int argc, unsigned char ** argv){
struct hostname *hostnamel=NULL; struct hostname *hostnamel=NULL;
int res; int res;
acl = myalloc(sizeof(struct ace)); acl = malloc(sizeof(struct ace));
if(!acl) return acl; if(!acl) return acl;
memset(acl, 0, sizeof(struct ace)); memset(acl, 0, sizeof(struct ace));
if(argc > 0 && strcmp("*", (char *)argv[0])) { if(argc > 0 && strcmp("*", (char *)argv[0])) {
@ -924,10 +915,10 @@ struct ace * make_ace (int argc, unsigned char ** argv){
arg = (unsigned char *)strtok((char *)arg, ","); arg = (unsigned char *)strtok((char *)arg, ",");
if(arg) do { if(arg) do {
if(!acl->users) { if(!acl->users) {
acl->users = userl = myalloc(sizeof(struct userlist)); acl->users = userl = malloc(sizeof(struct userlist));
} }
else { else {
userl->next = myalloc(sizeof(struct userlist)); userl->next = malloc(sizeof(struct userlist));
userl = userl -> next; userl = userl -> next;
} }
if(!userl) { if(!userl) {
@ -935,7 +926,7 @@ struct ace * make_ace (int argc, unsigned char ** argv){
return(NULL); return(NULL);
} }
memset(userl, 0, sizeof(struct userlist)); memset(userl, 0, sizeof(struct userlist));
userl->user=(unsigned char*)mystrdup((char *)arg); userl->user=(unsigned char*)strdup((char *)arg);
if(!userl->user) return NULL; if(!userl->user) return NULL;
} while((arg = (unsigned char *)strtok((char *)NULL, ","))); } while((arg = (unsigned char *)strtok((char *)NULL, ",")));
} }
@ -943,10 +934,10 @@ struct ace * make_ace (int argc, unsigned char ** argv){
arg = (unsigned char *)strtok((char *)argv[1], ","); arg = (unsigned char *)strtok((char *)argv[1], ",");
if(arg) do { if(arg) do {
if(!acl->src) { if(!acl->src) {
acl->src = ipl = myalloc(sizeof(struct iplist)); acl->src = ipl = malloc(sizeof(struct iplist));
} }
else { else {
ipl->next = myalloc(sizeof(struct iplist)); ipl->next = malloc(sizeof(struct iplist));
ipl = ipl -> next; ipl = ipl -> next;
} }
if(!ipl) { if(!ipl) {
@ -971,10 +962,10 @@ struct ace * make_ace (int argc, unsigned char ** argv){
if(scanipl(arg, &tmpip)){ if(scanipl(arg, &tmpip)){
if(!arglen) continue; if(!arglen) continue;
if(!acl->dstnames) { if(!acl->dstnames) {
acl->dstnames = hostnamel = myalloc(sizeof(struct hostname)); acl->dstnames = hostnamel = malloc(sizeof(struct hostname));
} }
else { else {
hostnamel->next = myalloc(sizeof(struct hostname)); hostnamel->next = malloc(sizeof(struct hostname));
hostnamel = hostnamel -> next; hostnamel = hostnamel -> next;
} }
if(!hostnamel){ if(!hostnamel){
@ -994,7 +985,7 @@ struct ace * make_ace (int argc, unsigned char ** argv){
arglen--; arglen--;
hostnamel->matchtype ^= MATCHBEGIN; hostnamel->matchtype ^= MATCHBEGIN;
} }
hostnamel->name = (unsigned char *) mystrdup( (char *)pattern); hostnamel->name = (unsigned char *) strdup( (char *)pattern);
if(!hostnamel->name) { if(!hostnamel->name) {
fprintf(stderr, "No memory for ACL entry, line %d\n", linenum); fprintf(stderr, "No memory for ACL entry, line %d\n", linenum);
return(NULL); return(NULL);
@ -1003,10 +994,10 @@ struct ace * make_ace (int argc, unsigned char ** argv){
else { else {
if(!acl->dst) { if(!acl->dst) {
acl->dst = ipl = myalloc(sizeof(struct iplist)); acl->dst = ipl = malloc(sizeof(struct iplist));
} }
else { else {
ipl->next = myalloc(sizeof(struct iplist)); ipl->next = malloc(sizeof(struct iplist));
ipl = ipl -> next; ipl = ipl -> next;
} }
if(!ipl) { if(!ipl) {
@ -1021,10 +1012,10 @@ struct ace * make_ace (int argc, unsigned char ** argv){
arg = (unsigned char *)strtok((char *)argv[3], ","); arg = (unsigned char *)strtok((char *)argv[3], ",");
if(arg) do { if(arg) do {
if(!acl->ports) { if(!acl->ports) {
acl->ports = portl = myalloc(sizeof(struct portlist)); acl->ports = portl = malloc(sizeof(struct portlist));
} }
else { else {
portl->next = myalloc(sizeof(struct portlist)); portl->next = malloc(sizeof(struct portlist));
portl = portl -> next; portl = portl -> next;
} }
if(!portl) { if(!portl) {
@ -1150,7 +1141,7 @@ struct ace * make_ace (int argc, unsigned char ** argv){
t2 = (t2 * 60) + (arg[12] - '0') * 10 + (arg[13] - '0'); t2 = (t2 * 60) + (arg[12] - '0') * 10 + (arg[13] - '0');
t2 = (t2 * 60) + (arg[15] - '0') * 10 + (arg[16] - '0'); t2 = (t2 * 60) + (arg[15] - '0') * 10 + (arg[16] - '0');
if(t2 < t1) break; if(t2 < t1) break;
sp = myalloc(sizeof(struct period)); sp = malloc(sizeof(struct period));
if(sp){ if(sp){
sp->fromtime = t1; sp->fromtime = t1;
sp->totime = t2; sp->totime = t2;
@ -1229,14 +1220,17 @@ static int h_ace(int argc, unsigned char **argv){
acl->action = res; acl->action = res;
switch(acl->action){ switch(acl->action){
case REDIRECT: case REDIRECT:
acl->chains = myalloc(sizeof(struct chain)); acl->chains = malloc(sizeof(struct chain));
if(!acl->chains) { if(!acl->chains) {
freeacl(acl); freeacl(acl);
return(21); return(21);
} }
memset(acl->chains, 0, sizeof(struct chain)); memset(acl->chains, 0, sizeof(struct chain));
acl->chains->type = R_HTTP; acl->chains->type = R_HTTP;
if(!getip46(46, argv[1], (struct sockaddr *)&acl->chains->addr)) return 5; if(!getip46(46, argv[1], (struct sockaddr *)&acl->chains->addr)) {
freeacl(acl);
return 5;
}
*SAPORT(&acl->chains->addr) = htons((uint16_t)atoi((char *)argv[2])); *SAPORT(&acl->chains->addr) = htons((uint16_t)atoi((char *)argv[2]));
acl->chains->weight = 1000; acl->chains->weight = 1000;
case ALLOW: case ALLOW:
@ -1253,7 +1247,7 @@ static int h_ace(int argc, unsigned char **argv){
break; break;
case CONNLIM: case CONNLIM:
case NOCONNLIM: case NOCONNLIM:
ncl = myalloc(sizeof(struct connlim)); ncl = malloc(sizeof(struct connlim));
if(!ncl) { if(!ncl) {
freeacl(acl); freeacl(acl);
return(21); return(21);
@ -1264,7 +1258,7 @@ static int h_ace(int argc, unsigned char **argv){
sscanf((char *)argv[1], "%u", &ncl->rate); sscanf((char *)argv[1], "%u", &ncl->rate);
sscanf((char *)argv[2], "%u", &ncl->period); sscanf((char *)argv[2], "%u", &ncl->period);
} }
pthread_mutex_lock(&connlim_mutex); _3proxy_mutex_lock(&connlim_mutex);
if(!conf.connlimiter){ if(!conf.connlimiter){
conf.connlimiter = ncl; conf.connlimiter = ncl;
} }
@ -1274,13 +1268,13 @@ static int h_ace(int argc, unsigned char **argv){
for(cli = conf.connlimiter; cli->next; cli = cli->next); for(cli = conf.connlimiter; cli->next; cli = cli->next);
cli->next = ncl; cli->next = ncl;
} }
pthread_mutex_unlock(&connlim_mutex); _3proxy_mutex_unlock(&connlim_mutex);
break; break;
case BANDLIM: case BANDLIM:
case NOBANDLIM: case NOBANDLIM:
nbl = myalloc(sizeof(struct bandlim)); nbl = malloc(sizeof(struct bandlim));
if(!nbl) { if(!nbl) {
freeacl(acl); freeacl(acl);
return(21); return(21);
@ -1290,13 +1284,13 @@ static int h_ace(int argc, unsigned char **argv){
if(acl->action == BANDLIM) { if(acl->action == BANDLIM) {
sscanf((char *)argv[1], "%u", &nbl->rate); sscanf((char *)argv[1], "%u", &nbl->rate);
if(nbl->rate < 300) { if(nbl->rate < 300) {
myfree(nbl); free(nbl);
freeacl(acl); freeacl(acl);
fprintf(stderr, "Wrong bandwidth specified, line %d\n", linenum); fprintf(stderr, "Wrong bandwidth specified, line %d\n", linenum);
return(4); return(4);
} }
} }
pthread_mutex_lock(&bandlim_mutex); _3proxy_mutex_lock(&bandlim_mutex);
if(!strcmp((char *)argv[0], "bandlimin") || !strcmp((char *)argv[0], "nobandlimin")){ if(!strcmp((char *)argv[0], "bandlimin") || !strcmp((char *)argv[0], "nobandlimin")){
if(!conf.bandlimiter){ if(!conf.bandlimiter){
conf.bandlimiter = nbl; conf.bandlimiter = nbl;
@ -1320,7 +1314,7 @@ static int h_ace(int argc, unsigned char **argv){
} }
} }
conf.bandlimver++; conf.bandlimver++;
pthread_mutex_unlock(&bandlim_mutex); _3proxy_mutex_unlock(&bandlim_mutex);
break; break;
case COUNTIN: case COUNTIN:
@ -1330,7 +1324,7 @@ static int h_ace(int argc, unsigned char **argv){
case COUNTALL: case COUNTALL:
case NOCOUNTALL: case NOCOUNTALL:
if(!conf.trafcountfunc) conf.trafcountfunc = trafcountfunc; if(!conf.trafcountfunc) conf.trafcountfunc = trafcountfunc;
tl = myalloc(sizeof(struct trafcount)); tl = malloc(sizeof(struct trafcount));
if(!tl) { if(!tl) {
freeacl(acl); freeacl(acl);
return(21); return(21);
@ -1344,14 +1338,14 @@ static int h_ace(int argc, unsigned char **argv){
tl->comment = ( char *)argv[1]; tl->comment = ( char *)argv[1];
while(isdigit(*tl->comment))tl->comment++; while(isdigit(*tl->comment))tl->comment++;
if(*tl->comment== '/')tl->comment++; if(*tl->comment== '/')tl->comment++;
tl->comment = mystrdup(tl->comment); tl->comment = strdup(tl->comment);
sscanf((char *)argv[1], "%u", &tl->number); sscanf((char *)argv[1], "%u", &tl->number);
sscanf((char *)argv[3], "%lu", &lim); sscanf((char *)argv[3], "%lu", &lim);
tl->type = getrotate(*argv[2]); tl->type = getrotate(*argv[2]);
tl->traflim64 = ((uint64_t)lim)*(1024*1024); tl->traflim64 = ((uint64_t)lim)*(1024*1024);
if(!tl->traflim64) { if(!tl->traflim64) {
myfree(tl); free(tl);
freeacl(acl); freeacl(acl);
fprintf(stderr, "Wrong traffic limit specified, line %d\n", linenum); fprintf(stderr, "Wrong traffic limit specified, line %d\n", linenum);
return(6); return(6);
@ -1372,7 +1366,7 @@ static int h_ace(int argc, unsigned char **argv){
} }
} }
} }
pthread_mutex_lock(&tc_mutex); _3proxy_mutex_lock(&tc_mutex);
if(!conf.trafcounter){ if(!conf.trafcounter){
conf.trafcounter = tl; conf.trafcounter = tl;
} }
@ -1382,7 +1376,7 @@ static int h_ace(int argc, unsigned char **argv){
for(ntl = conf.trafcounter; ntl->next; ntl = ntl->next); for(ntl = conf.trafcounter; ntl->next; ntl = ntl->next);
ntl->next = tl; ntl->next = tl;
} }
pthread_mutex_unlock(&tc_mutex); _3proxy_mutex_unlock(&tc_mutex);
} }
return 0; return 0;
@ -1420,7 +1414,7 @@ static int h_radius(int argc, unsigned char **argv){
s++; s++;
} }
if( !getip46(46, argv[nradservers + 2], (struct sockaddr *)&radiuslist[nradservers].authaddr)) return 1; if( !getip46(46, argv[nradservers + 2], (struct sockaddr *)&radiuslist[nradservers].authaddr)) return 1;
if( s && !getip46(46, (unsigned char *)s+1, (struct sockaddr *)&radiuslist[nradservers].localaddr)) return 2; if( s && !getip46(46, (unsigned char *)s, (struct sockaddr *)&radiuslist[nradservers].localaddr)) return 2;
if(!*SAPORT(&radiuslist[nradservers].authaddr))*SAPORT(&radiuslist[nradservers].authaddr) = htons(1812); if(!*SAPORT(&radiuslist[nradservers].authaddr))*SAPORT(&radiuslist[nradservers].authaddr) = htons(1812);
port = ntohs(*SAPORT(&radiuslist[nradservers].authaddr)); port = ntohs(*SAPORT(&radiuslist[nradservers].authaddr));
radiuslist[nradservers].logaddr = radiuslist[nradservers].authaddr; radiuslist[nradservers].logaddr = radiuslist[nradservers].authaddr;
@ -1458,6 +1452,16 @@ static int h_authcache(int argc, unsigned char **argv){
} }
static int h_plugin(int argc, unsigned char **argv){ static int h_plugin(int argc, unsigned char **argv){
#ifdef WITH_SSL
if(argc >= 3 && !strcmp((char *)argv[2], "ssl_plugin")){
return 0;
}
#endif
#ifdef WITH_PCRE
if(argc >= 3 && !strcmp((char *)argv[2], "pcre_plugin")){
return 0;
}
#endif
#ifdef NOPLUGINS #ifdef NOPLUGINS
return 999; return 999;
#else #else
@ -1578,7 +1582,7 @@ static int h_chroot(int argc, unsigned char **argv){
p--; p--;
*p = 0; *p = 0;
} }
chrootp = mystrdup((char *)argv[1]); chrootp = strdup((char *)argv[1]);
if(!chrootp) return 21; if(!chrootp) return 21;
} }
if (gid && setregid(gid,gid)) { if (gid && setregid(gid,gid)) {
@ -1724,21 +1728,21 @@ int parsestr (unsigned char *str, unsigned char **argm, int nitems, unsigned cha
*str = 0; *str = 0;
space = 1; space = 1;
if(incbegin){ if(incbegin){
argc--; if(argc) argc--;
if((fd = open((char *)incbegin+1, O_RDONLY)) <= 0){ if((fd = open((char *)incbegin+1, O_RDONLY)) < 0){
fprintf(stderr, "Failed to open %s\n", incbegin+1); fprintf(stderr, "Failed to open %s\n", incbegin+1);
return -1; return -1;
} }
if((*bufsize - *inbuf) <STRINGBUF){ if((*bufsize - *inbuf) <STRINGBUF){
*bufsize += STRINGBUF; *bufsize += STRINGBUF;
if(!(buf = myrealloc(buf, *bufsize))){ if(!(buf = realloc(buf, *bufsize))){
fprintf(stderr, "Failed to allocate memory for %s\n", incbegin+1); fprintf(stderr, "Failed to allocate memory for %s\n", incbegin+1);
close(fd); close(fd);
return -1; return -1;
} }
} }
len = 0; len = 0;
if(argm[argc]!=(incbegin+1)) { if(argc > 0 && argm[argc]!=(incbegin+1)) {
len = (int)strlen((char *)argm[argc]); len = (int)strlen((char *)argm[argc]);
memmove(buf+*inbuf, argm[argc], len); memmove(buf+*inbuf, argm[argc], len);
} }
@ -1784,7 +1788,7 @@ int readconfig(FILE * fp){
struct commands * cm; struct commands * cm;
int res = 0; int res = 0;
if( !(buf = myalloc(bufsize)) || ! (argv = myalloc((NPARAMS + 1) * sizeof(unsigned char *))) ) { if( !(buf = malloc(bufsize)) || ! (argv = malloc((NPARAMS + 1) * sizeof(unsigned char *))) ) {
fprintf(stderr, "No memory for configuration"); fprintf(stderr, "No memory for configuration");
return(10); return(10);
} }
@ -1831,8 +1835,8 @@ int readconfig(FILE * fp){
fprintf(stderr, "Unknown command: '%s' line %d\n", argv[0], linenum); fprintf(stderr, "Unknown command: '%s' line %d\n", argv[0], linenum);
return(linenum); return(linenum);
} }
myfree(buf); free(buf);
myfree(argv); free(argv);
return 0; return 0;
} }
@ -1841,8 +1845,8 @@ int readconfig(FILE * fp){
void freepwl(struct passwords *pwl){ void freepwl(struct passwords *pwl){
for(; pwl; pwl = (struct passwords *)itfree(pwl, pwl->next)){ for(; pwl; pwl = (struct passwords *)itfree(pwl, pwl->next)){
if(pwl->user)myfree(pwl->user); if(pwl->user)free(pwl->user);
if(pwl->password)myfree(pwl->password); if(pwl->password)free(pwl->password);
} }
} }
@ -1852,7 +1856,6 @@ void freeconf(struct extparam *confp){
struct bandlim * blout; struct bandlim * blout;
struct connlim * cl; struct connlim * cl;
struct trafcount * tc; struct trafcount * tc;
struct passwords *pw;
struct ace *acl; struct ace *acl;
struct filemon *fm; struct filemon *fm;
int counterd, archiverc; int counterd, archiverc;
@ -1864,33 +1867,29 @@ void freeconf(struct extparam *confp){
pthread_mutex_lock(&tc_mutex); _3proxy_mutex_lock(&tc_mutex);
confp->trafcountfunc = NULL; confp->trafcountfunc = NULL;
tc = confp->trafcounter; tc = confp->trafcounter;
confp->trafcounter = NULL; confp->trafcounter = NULL;
counterd = confp->counterd; counterd = confp->counterd;
confp->counterd = -1; confp->counterd = -1;
confp->countertype = NONE; confp->countertype = NONE;
pthread_mutex_unlock(&tc_mutex); _3proxy_mutex_unlock(&tc_mutex);
pthread_mutex_lock(&bandlim_mutex); _3proxy_mutex_lock(&bandlim_mutex);
bl = confp->bandlimiter; bl = confp->bandlimiter;
blout = confp->bandlimiterout; blout = confp->bandlimiterout;
confp->bandlimiter = NULL; confp->bandlimiter = NULL;
confp->bandlimiterout = NULL; confp->bandlimiterout = NULL;
confp->bandlimfunc = NULL; confp->bandlimfunc = NULL;
confp->bandlimver++; confp->bandlimver++;
pthread_mutex_unlock(&bandlim_mutex); _3proxy_mutex_unlock(&bandlim_mutex);
pthread_mutex_lock(&connlim_mutex); _3proxy_mutex_lock(&connlim_mutex);
cl = confp->connlimiter; cl = confp->connlimiter;
confp->connlimiter = NULL; confp->connlimiter = NULL;
pthread_mutex_unlock(&connlim_mutex); _3proxy_mutex_unlock(&connlim_mutex);
pthread_mutex_lock(&pwl_mutex);
pw = confp->pwl;
confp->pwl = NULL;
pthread_mutex_unlock(&pwl_mutex);
destroyhashtable(&pwl_table);
confp->logfunc = lognone; confp->logfunc = lognone;
logformat = confp->logformat; logformat = confp->logformat;
@ -1929,13 +1928,12 @@ void freeconf(struct extparam *confp){
} }
if(tc)dumpcounters(tc,counterd); if(tc)dumpcounters(tc,counterd);
for(; tc; tc = (struct trafcount *) itfree(tc, tc->next)){ for(; tc; tc = (struct trafcount *) itfree(tc, tc->next)){
if(tc->comment)myfree(tc->comment); if(tc->comment)free(tc->comment);
freeacl(tc->ace); freeacl(tc->ace);
} }
freeacl(acl); freeacl(acl);
freepwl(pw);
for(; bl; bl = (struct bandlim *) itfree(bl, bl->next)) freeacl(bl->ace); for(; bl; bl = (struct bandlim *) itfree(bl, bl->next)) freeacl(bl->ace);
for(; blout; blout = (struct bandlim *) itfree(blout, blout->next))freeacl(blout->ace); for(; blout; blout = (struct bandlim *) itfree(blout, blout->next))freeacl(blout->ace);
for(; cl; cl = (struct connlim *) itfree(cl, cl->next)) freeacl(cl->ace); for(; cl; cl = (struct connlim *) itfree(cl, cl->next)) freeacl(cl->ace);
@ -1944,14 +1942,14 @@ void freeconf(struct extparam *confp){
close(counterd); close(counterd);
} }
for(; fm; fm = (struct filemon *)itfree(fm, fm->next)){ for(; fm; fm = (struct filemon *)itfree(fm, fm->next)){
if(fm->path) myfree(fm->path); if(fm->path) free(fm->path);
} }
if(logformat) { if(logformat) {
myfree(logformat); free(logformat);
} }
if(archiver) { if(archiver) {
for(i = 0; i < archiverc; i++) myfree(archiver[i]); for(i = 0; i < archiverc; i++) free(archiver[i]);
myfree(archiver); free(archiver);
} }
havelog = 0; havelog = 0;
} }
@ -1960,7 +1958,13 @@ int reload (void){
FILE *fp; FILE *fp;
int error = -2; int error = -2;
pthread_mutex_lock(&config_mutex); _3proxy_mutex_lock(&config_mutex);
#ifdef WITH_SSL
ssl_install();
#endif
#ifdef WITH_PCRE
pcre_install();
#endif
conf.paused++; conf.paused++;
freeconf(&conf); freeconf(&conf);
conf.paused++; conf.paused++;
@ -1974,6 +1978,6 @@ int reload (void){
} }
if(!writable)fclose(fp); if(!writable)fclose(fp);
} }
pthread_mutex_unlock(&config_mutex); _3proxy_mutex_unlock(&config_mutex);
return error; return error;
} }

View File

@ -1,5 +1,5 @@
/* /*
(c) 2002-2021 by Vladimir Dubrovin <3proxy@3proxy.org> (c) 2002-2026 by Vladimir Dubrovin <vlad@3proxy.org>
please read License Agreement please read License Agreement
@ -132,6 +132,12 @@ static void pr_string(struct node *node, CBFUNC cbf, void*cb){
else (*cbf)(cb, "(NULL)", 6); else (*cbf)(cb, "(NULL)", 6);
} }
static void pr_password(struct node *node, CBFUNC cbf, void*cb){
if(node->value && *(unsigned char *)node->value){
(*cbf)(cb, "********", 8);
}
}
static void pr_rotation(struct node *node, CBFUNC cbf, void*cb){ static void pr_rotation(struct node *node, CBFUNC cbf, void*cb){
char * lstrings[] = { char * lstrings[] = {
"N", "C", "H", "D", "W", "M", "Y", "N" "N", "C", "H", "D", "W", "M", "Y", "N"
@ -239,6 +245,18 @@ static void pr_userlist(struct node *node, CBFUNC cbf, void*cb){
} }
} }
static void pr_hostname(struct node *node, CBFUNC cbf, void*cb){
struct hostname *hl = (struct hostname *)node->value;
if(!hl) {
(*cbf)(cb, "*", 1);
return;
}
for(; hl; hl = hl->next){
(*cbf)(cb, (char *)hl->name, (int)strlen((char *)hl->name));
if(hl->next)(*cbf)(cb, ",", 1);
}
}
int printiple(char *buf, struct iplist* ipl){ int printiple(char *buf, struct iplist* ipl){
int addrlen = (ipl->family == AF_INET6)?16:4, i; int addrlen = (ipl->family == AF_INET6)?16:4, i;
i = myinet_ntop(ipl->family, &ipl->ip_from, buf, addrlen); i = myinet_ntop(ipl->family, &ipl->ip_from, buf, addrlen);
@ -315,11 +333,25 @@ static void * ef_pwlist_type(struct node * node){
return "NT"; return "NT";
case LM: case LM:
return "LM"; return "LM";
case UN:
return "UN";
default: default:
return "UNKNOWN"; return "UNKNOWN";
} }
} }
static void * ef_hostname_next(struct node * node){
return ((struct hostname *)node->value) -> next;
}
static void * ef_hostname_name(struct node * node){
return ((struct hostname *)node->value) -> name;
}
static void * ef_hostname_matchtype(struct node * node){
return &((struct hostname *)node->value) -> matchtype;
}
static void * ef_chain_next(struct node * node){ static void * ef_chain_next(struct node * node){
return ((struct chain *)node->value) -> next; return ((struct chain *)node->value) -> next;
} }
@ -349,6 +381,18 @@ static void * ef_chain_password(struct node * node){
return ((struct chain *)node->value) -> extpass; return ((struct chain *)node->value) -> extpass;
} }
static void * ef_chain_secure(struct node * node){
return &((struct chain *)node->value) -> secure;
}
static void * ef_chain_exthost(struct node * node){
return ((struct chain *)node->value) -> exthost;
}
static void * ef_chain_cidr(struct node * node){
return &((struct chain *)node->value) -> cidr;
}
static void * ef_ace_next(struct node * node){ static void * ef_ace_next(struct node * node){
return ((struct ace *)node->value) -> next; return ((struct ace *)node->value) -> next;
} }
@ -379,6 +423,9 @@ static void * ef_ace_dst(struct node * node){
return ((struct ace *)node->value) -> dst; return ((struct ace *)node->value) -> dst;
} }
static void * ef_ace_dstnames(struct node * node){
return ((struct ace *)node->value) -> dstnames;
}
static void * ef_ace_ports(struct node * node){ static void * ef_ace_ports(struct node * node){
return ((struct ace *)node->value) -> ports; return ((struct ace *)node->value) -> ports;
@ -396,6 +443,13 @@ static void * ef_ace_period(struct node * node){
return ((struct ace *)node->value) -> periods; return ((struct ace *)node->value) -> periods;
} }
static void * ef_ace_weight(struct node * node){
return &((struct ace *)node->value) -> weight;
}
static void * ef_ace_nolog(struct node * node){
return &((struct ace *)node->value) -> nolog;
}
static void * ef_bandlimit_next(struct node * node){ static void * ef_bandlimit_next(struct node * node){
return ((struct bandlim *)node->value) -> next; return ((struct bandlim *)node->value) -> next;
@ -489,6 +543,14 @@ static void * ef_server_childcount(struct node * node){
return &((struct srvparam *)node->value) -> childcount; return &((struct srvparam *)node->value) -> childcount;
} }
static void * ef_server_maxchild(struct node * node){
return &((struct srvparam *)node->value) -> maxchild;
}
static void * ef_server_backlog(struct node * node){
return &((struct srvparam *)node->value) -> backlog;
}
static void * ef_server_log(struct node * node){ static void * ef_server_log(struct node * node){
if(((struct srvparam *)node->value) -> logfunc == lognone) return "none"; if(((struct srvparam *)node->value) -> logfunc == lognone) return "none";
#ifndef NORADIUS #ifndef NORADIUS
@ -499,7 +561,7 @@ static void * ef_server_log(struct node * node){
#ifndef _WIN32 #ifndef _WIN32
else if(((struct srvparam *)node->value) -> logfunc == logsyslog) return "syslog"; else if(((struct srvparam *)node->value) -> logfunc == logsyslog) return "syslog";
#endif #endif
#ifndef NOODBC #ifdef WITH_ODBC
else if(((struct srvparam *)node->value) -> logfunc == logsql) return "odbc"; else if(((struct srvparam *)node->value) -> logfunc == logsql) return "odbc";
#endif #endif
return NULL; return NULL;
@ -545,16 +607,68 @@ static void * ef_server_extsa6(struct node * node){
} }
#endif #endif
static void * ef_server_intNat(struct node * node){
return &((struct srvparam *)node->value) -> intNat;
}
static void * ef_server_extNat(struct node * node){
return &((struct srvparam *)node->value) -> extNat;
}
static void * ef_server_acl(struct node * node){ static void * ef_server_acl(struct node * node){
return ((struct srvparam *)node->value) -> acl; return ((struct srvparam *)node->value) -> acl;
} }
static void * ef_server_singlepacket(struct node * node){ static void * ef_server_singlepacket(struct node * node){
return &((struct srvparam *)node->value) -> singlepacket; return &((struct srvparam *)node->value) -> s_option;
} }
static void * ef_server_usentlm(struct node * node){ static void * ef_server_needuser(struct node * node){
return &((struct srvparam *)node->value) -> usentlm; return &((struct srvparam *)node->value) -> needuser;
}
static void * ef_server_transparent(struct node * node){
return &((struct srvparam *)node->value) -> transparent;
}
static void * ef_server_anonymous(struct node * node){
return &((struct srvparam *)node->value) -> anonymous;
}
static void * ef_server_requirecert(struct node * node){
return &((struct srvparam *)node->value) -> requirecert;
}
static void * ef_server_haproxy(struct node * node){
return &((struct srvparam *)node->value) -> haproxy;
}
static void * ef_server_authcachetype(struct node * node){
return &((struct srvparam *)node->value) -> authcachetype;
}
static void * ef_server_authcachetime(struct node * node){
return &((struct srvparam *)node->value) -> authcachetime;
}
static void * ef_server_gracetraf(struct node * node){
return &((struct srvparam *)node->value) -> gracetraf;
}
static void * ef_server_gracenum(struct node * node){
return &((struct srvparam *)node->value) -> gracenum;
}
static void * ef_server_gracedelay(struct node * node){
return &((struct srvparam *)node->value) -> gracedelay;
}
static void * ef_server_logdumpsrv(struct node * node){
return &((struct srvparam *)node->value) -> logdumpsrv;
}
static void * ef_server_logdumpcli(struct node * node){
return &((struct srvparam *)node->value) -> logdumpcli;
} }
static void * ef_server_starttime(struct node * node){ static void * ef_server_starttime(struct node * node){
@ -618,6 +732,26 @@ static void * ef_client_pwtype(struct node * node){
return &((struct clientparam *)node->value) -> pwtype; return &((struct clientparam *)node->value) -> pwtype;
} }
static void * ef_client_redirtype(struct node * node){
int i;
for(i=0; redirs[i].name; i++){
if(((struct clientparam *)node->value) -> redirtype == redirs[i].redir) return redirs[i].name;
}
return "";
}
static void * ef_client_weight(struct node * node){
return &((struct clientparam *)node->value) -> weight;
}
static void * ef_client_nolog(struct node * node){
return &((struct clientparam *)node->value) -> nolog;
}
static void * ef_client_transparent(struct node * node){
return &((struct clientparam *)node->value) -> transparent;
}
static void * ef_client_threadid(struct node * node){ static void * ef_client_threadid(struct node * node){
return &((struct clientparam *)node->value) -> threadid; return &((struct clientparam *)node->value) -> threadid;
} }
@ -651,155 +785,179 @@ static void * ef_period_next(struct node * node){
} }
static struct property prop_portlist[] = { static struct property prop_portlist[] = {
{prop_portlist + 1, "start", ef_portlist_start, TYPE_PORT, "port range start"}, {"start", ef_portlist_start, TYPE_PORT, "port range start"},
{prop_portlist + 2, "end", ef_portlist_end, TYPE_PORT, "port range end"}, {"end", ef_portlist_end, TYPE_PORT, "port range end"},
{NULL, "next", ef_portlist_next, TYPE_PORTLIST, "next"} {"next", ef_portlist_next, TYPE_PORTLIST, "next"}
}; };
static struct property prop_userlist[] = { static struct property prop_userlist[] = {
{prop_userlist+1, "user", ef_userlist_user, TYPE_STRING, "user name"}, {"user", ef_userlist_user, TYPE_STRING, "user name"},
{NULL, "next", ef_userlist_next, TYPE_USERLIST, "next"} {"next", ef_userlist_next, TYPE_USERLIST, "next"}
};
static struct property prop_hostname[] = {
{"name", ef_hostname_name, TYPE_STRING, "hostname pattern"},
{"matchtype", ef_hostname_matchtype, TYPE_INTEGER, "match type"},
{"next", ef_hostname_next, TYPE_HOSTNAME, "next"}
}; };
static struct property prop_pwlist[] = { static struct property prop_pwlist[] = {
{prop_pwlist + 1, "user", ef_pwlist_user, TYPE_STRING, "user name"}, {"user", ef_pwlist_user, TYPE_STRING, "user name"},
{prop_pwlist + 2, "password", ef_pwlist_password, TYPE_STRING, "password string"}, {"password", ef_pwlist_password, TYPE_PASSWORD, "password string"},
{prop_pwlist + 3, "type", ef_pwlist_type, TYPE_STRING, "password type"}, {"type", ef_pwlist_type, TYPE_STRING, "password type"},
{NULL, "next", ef_pwlist_next, TYPE_PWLIST, "next"} {"next", ef_pwlist_next, TYPE_PWLIST, "next"}
}; };
static struct property prop_chain[] = { static struct property prop_chain[] = {
{prop_chain + 1, "addr", ef_chain_addr, TYPE_SA, "parent address"}, {"addr", ef_chain_addr, TYPE_SA, "parent address"},
{prop_chain + 2, "type", ef_chain_type, TYPE_STRING, "parent type"}, {"type", ef_chain_type, TYPE_STRING, "parent type"},
{prop_chain + 3, "weight", ef_chain_weight, TYPE_SHORT, "parent weight 0-1000"}, {"weight", ef_chain_weight, TYPE_SHORT, "parent weight 0-1000"},
{prop_chain + 4, "user", ef_chain_user, TYPE_STRING, "parent login"}, {"user", ef_chain_user, TYPE_STRING, "parent login"},
{prop_chain + 5, "password", ef_chain_password, TYPE_STRING, "parent password"}, {"password", ef_chain_password, TYPE_PASSWORD, "parent password"},
{NULL, "next", ef_chain_next, TYPE_CHAIN, "next"} {"secure", ef_chain_secure, TYPE_INTEGER, "secure mode"},
{"exthost", ef_chain_exthost, TYPE_STRING, "external hostname"},
{"cidr", ef_chain_cidr, TYPE_SHORT, "CIDR"},
{"next", ef_chain_next, TYPE_CHAIN, "next"}
}; };
static struct property prop_period[] = { static struct property prop_period[] = {
{prop_period + 1, "fromtime", ef_period_fromtime, TYPE_TIME, "from time" }, {"fromtime", ef_period_fromtime, TYPE_TIME, "from time" },
{prop_period + 2, "totime", ef_period_totime, TYPE_TIME, "to time" }, {"totime", ef_period_totime, TYPE_TIME, "to time" },
{NULL, "next", ef_period_next, TYPE_PERIOD, "next"} {"next", ef_period_next, TYPE_PERIOD, "next"}
}; };
static struct property prop_ace[] = { static struct property prop_ace[] = {
{prop_ace + 1, "type", ef_ace_type, TYPE_STRING, "ace action"}, {"type", ef_ace_type, TYPE_STRING, "ace action"},
{prop_ace + 2, "operations", ef_ace_operations, TYPE_OPERATIONS, "request type"}, {"operations", ef_ace_operations, TYPE_OPERATIONS, "request type"},
{prop_ace + 3, "users", ef_ace_users, TYPE_USERLIST, "list of users"}, {"users", ef_ace_users, TYPE_USERLIST, "list of users"},
{prop_ace + 4, "src", ef_ace_src, TYPE_IPLIST, "list of source ips"}, {"src", ef_ace_src, TYPE_IPLIST, "list of source ips"},
{prop_ace + 5, "dst", ef_ace_dst, TYPE_IPLIST, "list of destination ips"}, {"dst", ef_ace_dst, TYPE_IPLIST, "list of destination ips"},
{prop_ace + 6, "ports", ef_ace_ports, TYPE_PORTLIST, "list of destination ports"}, {"dstnames", ef_ace_dstnames, TYPE_HOSTNAME, "list of destination hostnames"},
{prop_ace + 7, "chain", ef_ace_chain, TYPE_CHAIN, "redirect to parent(s)"}, {"ports", ef_ace_ports, TYPE_PORTLIST, "list of destination ports"},
{prop_ace + 8, "wdays", ef_ace_weekdays, TYPE_WEEKDAYS, "days of week"}, {"chain", ef_ace_chain, TYPE_CHAIN, "redirect to parent(s)"},
{prop_ace + 9, "periods", ef_ace_period, TYPE_PERIOD, "time of the day"}, {"wdays", ef_ace_weekdays, TYPE_WEEKDAYS, "days of week"},
{NULL, "next", ef_ace_next, TYPE_ACE, "next"} {"periods", ef_ace_period, TYPE_PERIOD, "time of the day"},
{"weight", ef_ace_weight, TYPE_INTEGER, "ace weight"},
{"nolog", ef_ace_nolog, TYPE_INTEGER, "do not log"},
{"next", ef_ace_next, TYPE_ACE, "next"}
}; };
static struct property prop_bandlimit[] = { static struct property prop_bandlimit[] = {
{prop_bandlimit + 1, "ace", ef_bandlimit_ace, TYPE_ACE, "acl to apply"}, {"ace", ef_bandlimit_ace, TYPE_ACE, "acl to apply"},
{prop_bandlimit + 2, "rate", ef_bandlimit_rate, TYPE_UNSIGNED, "max allowed bandwidth"}, {"rate", ef_bandlimit_rate, TYPE_UNSIGNED, "max allowed bandwidth"},
{NULL, "next", ef_bandlimit_next, TYPE_BANDLIMIT, "next"} {"next", ef_bandlimit_next, TYPE_BANDLIMIT, "next"}
}; };
static struct property prop_trafcounter[] = { static struct property prop_trafcounter[] = {
{prop_trafcounter + 1, "disabled", ef_trafcounter_disabled, TYPE_INTEGER, "counter status"}, {"disabled", ef_trafcounter_disabled, TYPE_INTEGER, "counter status"},
{prop_trafcounter + 2, "ace", ef_trafcounter_ace, TYPE_ACE, "traffic to count"}, {"ace", ef_trafcounter_ace, TYPE_ACE, "traffic to count"},
{prop_trafcounter + 3, "number", ef_trafcounter_number, TYPE_UNSIGNED, "counter number"}, {"number", ef_trafcounter_number, TYPE_UNSIGNED, "counter number"},
{prop_trafcounter + 4, "type", ef_trafcounter_type, TYPE_ROTATION, "rotation type"}, {"type", ef_trafcounter_type, TYPE_ROTATION, "rotation type"},
{"traffic", ef_trafcounter_traffic64, TYPE_UNSIGNED64, "counter value"},
{"limit", ef_trafcounter_limit64, TYPE_UNSIGNED64, "counter limit"},
{prop_trafcounter + 5, "traffic", ef_trafcounter_traffic64, TYPE_UNSIGNED64, "counter value"}, {"cleared", ef_trafcounter_cleared, TYPE_DATETIME, "last rotated"},
{prop_trafcounter + 6, "limit", ef_trafcounter_limit64, TYPE_UNSIGNED64, "counter limit"}, {"updated", ef_trafcounter_updated, TYPE_DATETIME, "last updated"},
{prop_trafcounter + 7, "cleared", ef_trafcounter_cleared, TYPE_DATETIME, "last rotated"}, {"comment", ef_trafcounter_comment, TYPE_STRING, "counter comment"},
{prop_trafcounter + 8, "updated", ef_trafcounter_updated, TYPE_DATETIME, "last updated"}, {"next", ef_trafcounter_next, TYPE_TRAFCOUNTER, "next"}
{prop_trafcounter + 9, "comment", ef_trafcounter_comment, TYPE_STRING, "counter comment"},
{NULL, "next", ef_trafcounter_next, TYPE_TRAFCOUNTER}
}; };
/*
*/
static struct property prop_server[] = { static struct property prop_server[] = {
{prop_server + 1, "servicetype", ef_server_type, TYPE_STRING, "type of the service/client"}, {"servicetype", ef_server_type, TYPE_STRING, "type of the service/client"},
{prop_server + 2, "target", ef_server_target, TYPE_STRING, "portmapper target ip"}, {"target", ef_server_target, TYPE_STRING, "portmapper target ip"},
{prop_server + 3, "targetport", ef_server_targetport, TYPE_PORT, "portmapper target port"}, {"targetport", ef_server_targetport, TYPE_PORT, "portmapper target port"},
{prop_server + 4, "starttime", ef_server_starttime, TYPE_DATETIME, "service started seconds"}, {"starttime", ef_server_starttime, TYPE_DATETIME, "service started seconds"},
{prop_server + 5, "auth", ef_server_auth, TYPE_STRING, "service authentication type"}, {"auth", ef_server_auth, TYPE_STRING, "service authentication type"},
{prop_server + 6, "acl", ef_server_acl, TYPE_ACE, "access control list"}, {"acl", ef_server_acl, TYPE_ACE, "access control list"},
{prop_server + 7, "singlepacket", ef_server_singlepacket, TYPE_INTEGER, "is single packet redirection"}, {"singlepacket", ef_server_singlepacket, TYPE_INTEGER, "is single packet redirection"},
{prop_server + 8, "usentlm", ef_server_usentlm, TYPE_INTEGER, "allow NTLM authentication"}, {"log", ef_server_log, TYPE_STRING, "type of logging"},
{prop_server + 9, "log", ef_server_log, TYPE_STRING, "type of logging"}, {"logtarget", ef_server_logtarget, TYPE_STRING, "log target options"},
{prop_server + 10, "logtarget", ef_server_logtarget, TYPE_STRING, "log target options"}, {"logformat", ef_server_logformat, TYPE_STRING, "logging format string"},
{prop_server + 11, "logformat", ef_server_logformat, TYPE_STRING, "logging format string"}, {"nonprintable", ef_server_nonprintable, TYPE_STRING, "non printable characters"},
{prop_server + 12, "nonprintable", ef_server_nonprintable, TYPE_STRING, "non printable characters"}, {"replacement", ef_server_replacement, TYPE_CHAR, "replacement character"},
{prop_server + 13, "replacement", ef_server_replacement, TYPE_CHAR, "replacement character"}, {"childcount", ef_server_childcount, TYPE_INTEGER, "number of servers connected"},
{prop_server + 14, "childcount", ef_server_childcount, TYPE_INTEGER, "number of servers connected"}, {"maxchild", ef_server_maxchild, TYPE_INTEGER, "max concurrent connections"},
{prop_server + 15, "intsa", ef_server_intsa, TYPE_SA, "ip address of internal interface"}, {"backlog", ef_server_backlog, TYPE_INTEGER, "listen backlog"},
{prop_server + 16, "extsa", ef_server_extsa, TYPE_SA, "ip address of external interface"}, {"needuser", ef_server_needuser, TYPE_INTEGER, "require user authentication"},
{"transparent", ef_server_transparent, TYPE_INTEGER, "transparent proxy"},
{"anonymous", ef_server_anonymous, TYPE_INTEGER, "anonymous mode"},
{"requirecert", ef_server_requirecert, TYPE_INTEGER, "require client certificate"},
{"haproxy", ef_server_haproxy, TYPE_INTEGER, "HAProxy protocol"},
{"authcachetype", ef_server_authcachetype, TYPE_UNSIGNED, "authentication cache type"},
{"authcachetime", ef_server_authcachetime, TYPE_UNSIGNED, "authentication cache time"},
{"gracetraf", ef_server_gracetraf, TYPE_INTEGER, "grace traffic"},
{"gracenum", ef_server_gracenum, TYPE_INTEGER, "grace number"},
{"gracedelay", ef_server_gracedelay, TYPE_INTEGER, "grace delay"},
{"logdumpsrv", ef_server_logdumpsrv, TYPE_UNSIGNED, "log dump server traffic"},
{"logdumpcli", ef_server_logdumpcli, TYPE_UNSIGNED, "log dump client traffic"},
{"intsa", ef_server_intsa, TYPE_SA, "ip address of internal interface"},
{"extsa", ef_server_extsa, TYPE_SA, "ip address of external interface"},
{"intnat", ef_server_intNat, TYPE_SA, "internal NAT address"},
{"extnat", ef_server_extNat, TYPE_SA, "external NAT address"},
#ifndef NOIPV6 #ifndef NOIPV6
{prop_server + 17, "extsa6", ef_server_extsa6, TYPE_SA, "ipv6 address of external interface"}, {"extsa6", ef_server_extsa6, TYPE_SA, "ipv6 address of external interface"},
{prop_server + 18, "child", ef_server_child, TYPE_CLIENT, "connected clients"},
#else
{prop_server + 17, "child", ef_server_child, TYPE_CLIENT, "connected clients"},
#endif #endif
{NULL, "next", ef_server_next, TYPE_SERVER, "next"} {"child", ef_server_child, TYPE_CLIENT, "connected clients"},
{"next", ef_server_next, TYPE_SERVER, "next"}
}; };
static struct property prop_client[] = { static struct property prop_client[] = {
{prop_client + 1, "servicetype", ef_client_type, TYPE_STRING, "type of the client"}, {"servicetype", ef_client_type, TYPE_STRING, "type of the client"},
{prop_client + 2, "threadid", ef_client_threadid, TYPE_UNSIGNED64, "process thread id"}, {"threadid", ef_client_threadid, TYPE_UNSIGNED64, "process thread id"},
{prop_client + 3, "starttime", ef_client_starttime, TYPE_DATETIME, "client started seconds"}, {"starttime", ef_client_starttime, TYPE_DATETIME, "client started seconds"},
{prop_client + 4, "starttime_msec", ef_client_starttime_msec, TYPE_UNSIGNED, "client started milliseconds"}, {"starttime_msec", ef_client_starttime_msec, TYPE_UNSIGNED, "client started milliseconds"},
{prop_client + 5, "redirected", ef_client_redirected, TYPE_INTEGER, "number of redirections"}, {"redirected", ef_client_redirected, TYPE_INTEGER, "number of redirections"},
{prop_client + 6, "operation", ef_client_operation, TYPE_OPERATIONS, "action requested by client"}, {"operation", ef_client_operation, TYPE_OPERATIONS, "action requested by client"},
{prop_client + 7, "hostname", ef_client_hostname, TYPE_STRING, "name of the requested host"}, {"hostname", ef_client_hostname, TYPE_STRING, "name of the requested host"},
{prop_client + 8, "extusername", ef_client_extusername, TYPE_STRING, "username for requested host"}, {"extusername", ef_client_extusername, TYPE_STRING, "username for requested host"},
{prop_client + 9, "extpassword", ef_client_extpassword, TYPE_STRING, "password for requested host"}, {"extpassword", ef_client_extpassword, TYPE_PASSWORD, "password for requested host"},
{prop_client + 10, "username", ef_client_username, TYPE_STRING, "client username"}, {"username", ef_client_username, TYPE_STRING, "client username"},
{prop_client + 11, "password", ef_client_password, TYPE_STRING, "client password"}, {"password", ef_client_password, TYPE_PASSWORD, "client password"},
{prop_client + 12, "clisa", ef_client_clisa, TYPE_SA, "client sa"}, {"clisa", ef_client_clisa, TYPE_SA, "client sa"},
{prop_client + 13, "srvsa", ef_client_srvsa, TYPE_SA, "target server sa"}, {"srvsa", ef_client_srvsa, TYPE_SA, "target server sa"},
{prop_client + 14, "reqsa", ef_client_reqsa, TYPE_SA, "requested server sa"}, {"reqsa", ef_client_reqsa, TYPE_SA, "requested server sa"},
{prop_client + 15, "bytesin", ef_client_bytesin64, TYPE_UNSIGNED64, "bytes from server to client"}, {"bytesin", ef_client_bytesin64, TYPE_UNSIGNED64, "bytes from server to client"},
{prop_client + 16, "bytesout", ef_client_bytesout64, TYPE_UNSIGNED64, "bytes from client to server"}, {"bytesout", ef_client_bytesout64, TYPE_UNSIGNED64, "bytes from client to server"},
{prop_client + 17, "maxtrafin", ef_client_maxtrafin64, TYPE_UNSIGNED64, "maximum traffic allowed for download"}, {"maxtrafin", ef_client_maxtrafin64, TYPE_UNSIGNED64, "maximum traffic allowed for download"},
{prop_client + 18, "maxtrafout", ef_client_maxtrafout64, TYPE_UNSIGNED64, "maximum traffic allowed for upload"}, {"maxtrafout", ef_client_maxtrafout64, TYPE_UNSIGNED64, "maximum traffic allowed for upload"},
{prop_client + 19, "pwtype", ef_client_pwtype, TYPE_INTEGER, "type of client password"}, {"pwtype", ef_client_pwtype, TYPE_INTEGER, "type of client password"},
{prop_client + 20, "clisock", ef_client_clisock, TYPE_INTEGER, "client socket"}, {"redirtype", ef_client_redirtype, TYPE_STRING, "redirection type"},
{prop_client + 21, "remsock", ef_client_remsock, TYPE_INTEGER, "remote socket"}, {"weight", ef_client_weight, TYPE_INTEGER, "weight"},
{NULL, "next", ef_client_next, TYPE_CLIENT, "next"} {"nolog", ef_client_nolog, TYPE_INTEGER, "do not log"},
{"transparent", ef_client_transparent, TYPE_INTEGER, "transparent proxy"},
{"clisock", ef_client_clisock, TYPE_INTEGER, "client socket"},
{"remsock", ef_client_remsock, TYPE_INTEGER, "remote socket"},
{"next", ef_client_next, TYPE_CLIENT, "next"}
}; };
struct datatype datatypes[64] = { struct datatype datatypes[64] = {
{"integer", NULL, pr_integer, NULL}, {"integer", NULL, pr_integer, NULL, 0},
{"short", NULL, pr_short, NULL}, {"short", NULL, pr_short, NULL, 0},
{"char", NULL, pr_char, NULL}, {"char", NULL, pr_char, NULL, 0},
{"unsigned", NULL, pr_unsigned, NULL}, {"unsigned", NULL, pr_unsigned, NULL, 0},
{"unsigned64", NULL, pr_unsigned64, NULL}, {"unsigned64", NULL, pr_unsigned64, NULL, 0},
{"traffic", NULL, pr_traffic, NULL}, {"traffic", NULL, pr_traffic, NULL, 0},
{"port", NULL, pr_port, NULL}, {"port", NULL, pr_port, NULL, 0},
{"ip", NULL, pr_ip, NULL}, {"ip", NULL, pr_ip, NULL, 0},
{"sa", NULL, pr_sa, NULL}, {"sa", NULL, pr_sa, NULL, 0},
{"cidr", NULL, pr_cidr, NULL}, {"cidr", NULL, pr_cidr, NULL, 0},
{"string", NULL, pr_string, NULL}, {"string", NULL, pr_string, NULL, 0},
{"datetime", NULL, pr_datetime, NULL}, {"datetime", NULL, pr_datetime, NULL, 0},
{"operations", NULL, pr_operations, NULL}, {"operations", NULL, pr_operations, NULL, 0},
{"rotation", NULL, pr_rotation, NULL}, {"rotation", NULL, pr_rotation, NULL, 0},
{"portlist", ef_portlist_next, pr_portlist, prop_portlist}, {"portlist", ef_portlist_next, pr_portlist, prop_portlist, sizeof(prop_portlist)/sizeof(struct property)},
{"iplist", ef_iplist_next, pr_iplist, NULL}, {"iplist", ef_iplist_next, pr_iplist, NULL, 0},
{"userlist", ef_userlist_next, pr_userlist, prop_userlist}, {"userlist", ef_userlist_next, pr_userlist, prop_userlist, sizeof(prop_userlist)/sizeof(struct property)},
{"pwlist", ef_pwlist_next, NULL, prop_pwlist}, {"pwlist", ef_pwlist_next, NULL, prop_pwlist, sizeof(prop_pwlist)/sizeof(struct property)},
{"chain", ef_chain_next, NULL, prop_chain}, {"chain", ef_chain_next, NULL, prop_chain, sizeof(prop_chain)/sizeof(struct property)},
{"ace", ef_ace_next, NULL, prop_ace}, {"ace", ef_ace_next, NULL, prop_ace, sizeof(prop_ace)/sizeof(struct property)},
{"bandlimit", ef_bandlimit_next, NULL, prop_bandlimit}, {"bandlimit", ef_bandlimit_next, NULL, prop_bandlimit, sizeof(prop_bandlimit)/sizeof(struct property)},
{"trafcounter", ef_trafcounter_next, NULL, prop_trafcounter}, {"trafcounter", ef_trafcounter_next, NULL, prop_trafcounter, sizeof(prop_trafcounter)/sizeof(struct property)},
{"client", ef_client_next, NULL, prop_client}, {"client", ef_client_next, NULL, prop_client, sizeof(prop_client)/sizeof(struct property)},
{"weekdays", NULL, pr_wdays, NULL}, {"weekdays", NULL, pr_wdays, NULL, 0},
{"time", NULL, pr_time, NULL}, {"time", NULL, pr_time, NULL, 0},
{"period", ef_period_next, NULL, prop_period}, {"period", ef_period_next, NULL, prop_period, sizeof(prop_period)/sizeof(struct property)},
{"server", ef_server_next, NULL, prop_server} {"server", ef_server_next, NULL, prop_server, sizeof(prop_server)/sizeof(struct property)},
{"password", NULL, pr_password, NULL, 0},
{"hostname", ef_hostname_next, pr_hostname, prop_hostname, sizeof(prop_hostname)/sizeof(struct property)}
}; };

View File

@ -1,6 +1,6 @@
/* /*
3APA3A simplest proxy server 3APA3A simplest proxy server
(c) 2002-2021 by Vladimir Dubrovin <3proxy@3proxy.org> (c) 2002-2026 by Vladimir Dubrovin <vlad@3proxy.org>
please read License Agreement please read License Agreement
@ -33,7 +33,7 @@ void * dnsprchild(struct clientparam* param) {
#endif #endif
if(!(bbuf = myalloc(BUFSIZE+2))){ if(!(bbuf = malloc(BUFSIZE+2))){
param->srv->fds.events = POLLIN; param->srv->fds.events = POLLIN;
RETURN (21); RETURN (21);
} }
@ -75,14 +75,14 @@ void * dnsprchild(struct clientparam* param) {
} }
if(len > (i-4)) {RETURN(817);} if(len > (i-4)) {RETURN(817);}
host = mystrdup((char *)buf+13); host = strdup((char *)buf+13);
if(!host) {RETURN(21);} if(!host) {RETURN(21);}
for(s2 = buf + 12; (s1 = (unsigned char *)strchr((char *)s2 + 1, '.')); s2 = s1)*s2 = (unsigned char)((s1 - s2) - 1); for(s2 = buf + 12; (s1 = (unsigned char *)strchr((char *)s2 + 1, '.')); s2 = s1)*s2 = (unsigned char)((s1 - s2) - 1);
*s2 = (len - (int)(s2 - buf)) - 1; *s2 = (len - (int)(s2 - buf)) - 1;
type = ((unsigned)buf[len+1])*256 + (unsigned)buf[len+2]; type = ((unsigned)buf[len+1])*256 + (unsigned)buf[len+2];
if((type==0x01 || type==0x1c) && !param->srv->singlepacket){ if((type==0x01 || type==0x1c) && !param->srv->s_option){
ip = udpresolve((type==0x1c)?AF_INET6:AF_INET, (unsigned char *)host, addr, &ttl, param, 0); ip = udpresolve((type==0x1c)?AF_INET6:AF_INET, (unsigned char *)host, addr, &ttl, param, 0);
} }
@ -200,8 +200,8 @@ CLEANRET:
} }
dolog(param, buf); dolog(param, buf);
} }
if(bbuf)myfree(bbuf); if(bbuf)free(bbuf);
if(host)myfree(host); if(host)free(host);
#ifndef _WIN32 #ifndef _WIN32
param->clisock = INVALID_SOCKET; param->clisock = INVALID_SOCKET;
#endif #endif

View File

@ -1,5 +1,5 @@
/* /*
(c) 2002-2021 by Vladimir Dubrovin <3proxy@3proxy.org> (c) 2002-2026 by Vladimir Dubrovin <vlad@3proxy.org>
please read License Agreement please read License Agreement
@ -7,6 +7,18 @@
#include "proxy.h" #include "proxy.h"
/*
* Read one FTP server response, skipping continuation lines (lines whose
* 4th character is '-' per RFC 959). Returns the line length on success,
* 0/<0 on socket error/timeout. The final line's text is left in buf.
*/
static int ftpreadresponse(struct clientparam *param, char *buf, int buflen) {
int i;
while((i = sockgetlinebuf(param, SERVER, (unsigned char *)buf, buflen - 1, '\n',
conf.timeouts[STRING_L])) > 0
&& (i < 3 || !isnumber(*buf) || buf[3] == '-')) {}
return i;
}
int ftplogin(struct clientparam *param, char *nbuf, int *innbuf) { int ftplogin(struct clientparam *param, char *nbuf, int *innbuf) {
char tbuf[256]; char tbuf[256];
@ -20,8 +32,7 @@ int ftplogin(struct clientparam *param, char *nbuf, int *innbuf) {
if(innbuf)*innbuf = 0; if(innbuf)*innbuf = 0;
if(len < 140) return 707; if(len < 140) return 707;
while((i = sockgetlinebuf(param, SERVER, (unsigned char *)buf, len - 1, '\n', conf.timeouts[STRING_L])) > 0 && (i < 3 || !isnumber(*buf) || buf[3] == '-')){ i = ftpreadresponse(param, buf, len);
}
if(i < 3) return 706; if(i < 3) return 706;
buf[i] = 0; buf[i] = 0;
if(atoi(buf)/100 != 2) { if(atoi(buf)/100 != 2) {
@ -34,8 +45,7 @@ int ftplogin(struct clientparam *param, char *nbuf, int *innbuf) {
} }
param->statscli64 += (int)strlen(buf); param->statscli64 += (int)strlen(buf);
param->nwrites++; param->nwrites++;
while((i = sockgetlinebuf(param, SERVER, (unsigned char *)buf, len - 1, '\n', conf.timeouts[STRING_L])) > 0 && (i < 3 || !isnumber(*buf) || buf[3] == '-')){ i = ftpreadresponse(param, buf, len);
}
if(i < 3) return 704; if(i < 3) return 704;
buf[i] = 0; buf[i] = 0;
res = atoi(buf)/100; res = atoi(buf)/100;
@ -99,8 +109,7 @@ int ftpres(struct clientparam *param, unsigned char * buf, int l){
int i; int i;
if (l < 16) return 755; if (l < 16) return 755;
while((i = sockgetlinebuf(param, SERVER, buf, l - 1, '\n', conf.timeouts[STRING_L])) > 0 && (i < 3 || !isnumber(*buf) || buf[3] == '-')){ i = ftpreadresponse(param, (char *)buf, l);
}
buf[i] = 0; buf[i] = 0;
if(i < 3) return 751; if(i < 3) return 751;
if(buf[0] != '2' && buf[0] != '1') return 750; if(buf[0] != '2' && buf[0] != '1') return 750;
@ -115,8 +124,7 @@ int ftpsyst(struct clientparam *param, unsigned char *buf, unsigned len){
} }
param->statscli64 += 6; param->statscli64 += 6;
param->nwrites++; param->nwrites++;
while((i = sockgetlinebuf(param, SERVER, buf, len - 1, '\n', conf.timeouts[STRING_L])) > 0 && (i < 3 || !isnumber(*buf) || buf[3] == '-')){ i = ftpreadresponse(param, (char *)buf, len);
}
if(i < 7) return 722; if(i < 7) return 722;
buf[3] = 0; buf[3] = 0;
if(atoi((char *)buf)/100 != 2) return 723; if(atoi((char *)buf)/100 != 2) return 723;
@ -134,8 +142,7 @@ int ftppwd(struct clientparam *param, unsigned char *buf, unsigned len){
} }
param->statscli64 += 5; param->statscli64 += 5;
param->nwrites++; param->nwrites++;
while((i = sockgetlinebuf(param, SERVER, buf, len - 1, '\n', conf.timeouts[STRING_L])) > 0 && (i < 3 || !isnumber(*buf) || buf[3] == '-')){ i = ftpreadresponse(param, (char *)buf, len);
}
if(i < 7) return 732; if(i < 7) return 732;
buf[3] = 0; buf[3] = 0;
if(atoi((char *)buf)/100 != 2) return 733; if(atoi((char *)buf)/100 != 2) return 733;
@ -159,8 +166,7 @@ int ftptype(struct clientparam *param, unsigned char* f_type){
} }
param->statscli64 += (int)strlen(buf); param->statscli64 += (int)strlen(buf);
param->nwrites++; param->nwrites++;
while((i = sockgetlinebuf(param, SERVER, (unsigned char *)buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L])) > 0 && (i < 3 || !isnumber(*buf) || buf[3] == '-')){ i = ftpreadresponse(param, buf, sizeof(buf));
}
if(i < 3) return 742; if(i < 3) return 742;
if(buf[0] != '2') return 740; if(buf[0] != '2') return 740;
return 0; return 0;
@ -181,8 +187,7 @@ SOCKET ftpdata(struct clientparam *param){
} }
param->statscli64 += 6; param->statscli64 += 6;
param->nwrites++; param->nwrites++;
while((i = sockgetlinebuf(param, SERVER, (unsigned char *)buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L])) > 0 && (i < 3 || !isnumber(*buf) || buf[3] == '-')){ i = ftpreadresponse(param, buf, sizeof(buf));
}
if(i < 7) return INVALID_SOCKET; if(i < 7) return INVALID_SOCKET;
if(buf[0] != '2') return INVALID_SOCKET; if(buf[0] != '2') return INVALID_SOCKET;
buf[i-2] = 0; buf[i-2] = 0;
@ -195,7 +200,7 @@ SOCKET ftpdata(struct clientparam *param){
rem = param->remsock; rem = param->remsock;
param->remsock = INVALID_SOCKET; param->remsock = INVALID_SOCKET;
param->req = param->sinsr; param->req = param->sinsr;
*SAPORT(&param->req) = *SAPORT(&param->sinsr) = htons((uint16_t)((b5<<8)^b6)); *SAPORT(&param->req) = *SAPORT(&param->sinsr) = htons((uint16_t)(((b5 & 0xff)<<8) | (b6 & 0xff)));
*SAPORT(&param->sinsl) = 0; *SAPORT(&param->sinsl) = 0;
i = param->operation; i = param->operation;
param->operation = FTP_DATA; param->operation = FTP_DATA;
@ -233,8 +238,7 @@ SOCKET ftpcommand(struct clientparam *param, unsigned char * command, unsigned c
} }
param->statscli64 += (int)strlen(buf); param->statscli64 += (int)strlen(buf);
param->nwrites++; param->nwrites++;
while((i = sockgetlinebuf(param, SERVER, (unsigned char *)buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L])) > 0 && (i < 3 || !isnumber(*buf) || buf[3] == '-')){ i = ftpreadresponse(param, buf, sizeof(buf));
}
if(i < 3) { if(i < 3) {
param->srv->so._closesocket(param->sostate, s); param->srv->so._closesocket(param->sostate, s);
return INVALID_SOCKET; return INVALID_SOCKET;

Some files were not shown because too many files have changed in this diff Show More