mirror of
https://github.com/3proxy/3proxy.git
synced 2026-08-13 12:19:17 +08:00
Compare commits
12 Commits
2626e67984
...
03121bf916
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
03121bf916 | ||
|
|
6818872f63 | ||
|
|
81a4e5bae3 | ||
|
|
0ae2754c1e | ||
|
|
05f83896bf | ||
|
|
f668a34910 | ||
|
|
763e21e053 | ||
|
|
7b85f6a684 | ||
|
|
92d3b08dd2 | ||
|
|
4877b39f2c | ||
|
|
44c47ee7d9 | ||
|
|
ccdecfd832 |
4
.github/workflows/docker-test.yml
vendored
4
.github/workflows/docker-test.yml
vendored
@ -17,7 +17,7 @@ jobs:
|
||||
platform: [linux/amd64, linux/arm64]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v4
|
||||
@ -26,7 +26,7 @@ jobs:
|
||||
uses: docker/setup-buildx-action@v4
|
||||
|
||||
- name: Build image
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@v7
|
||||
with:
|
||||
context: .
|
||||
file: ${{ matrix.file }}
|
||||
|
||||
@ -51,7 +51,7 @@ option(3PROXY_USE_OPENSSL "Enable TLS/SSL support via OpenSSL (fallback when wol
|
||||
option(3PROXY_USE_PCRE2 "Enable PCRE2 regex filtering" 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_SPLICE "Use Linux splice() for zero-copy (Linux only)" ON)
|
||||
option(3PROXY_USE_SPLICE "Build Linux splice() support, slower than read/write for most traffic (Linux only)" OFF)
|
||||
option(3PROXY_USE_POLL "Use poll() instead of select() (Unix only)" ON)
|
||||
option(3PROXY_USE_WSAPOLL "Use WSAPoll instead of select() (Windows only)" ON)
|
||||
option(3PROXY_USE_NETFILTER "Enable Linux netfilter support (Linux only)" ON)
|
||||
@ -236,6 +236,12 @@ else()
|
||||
)
|
||||
endif()
|
||||
|
||||
# Unix domain sockets off: NO_UN also undefines WITH_UN if it arrives from
|
||||
# elsewhere, e.g. CFLAGS
|
||||
if(NOT 3PROXY_USE_UNIX_SOCKETS)
|
||||
add_compile_definitions(NO_UN)
|
||||
endif()
|
||||
|
||||
# Common definitions
|
||||
if(WIN32)
|
||||
# Windows: use WSAPOLL
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
|
||||
|
||||
FROM docker.io/alpine:latest AS wolfssl
|
||||
RUN apk add --no-cache build-base curl autoconf automake libtool
|
||||
RUN apk add --no-cache build-base curl autoconf automake libtool linux-headers
|
||||
RUN TAG=$(curl -s https://api.github.com/repos/wolfSSL/wolfssl/releases/latest \
|
||||
| sed -n 's/.*"tag_name": *"\([^"]*\)".*/\1/p') && \
|
||||
echo "wolfssl tag: $TAG" && \
|
||||
|
||||
@ -27,7 +27,7 @@
|
||||
#
|
||||
|
||||
FROM docker.io/alpine:latest AS wolfssl
|
||||
RUN apk add --no-cache build-base curl autoconf automake libtool
|
||||
RUN apk add --no-cache build-base curl autoconf automake libtool linux-headers
|
||||
RUN TAG=$(curl -s https://api.github.com/repos/wolfSSL/wolfssl/releases/latest \
|
||||
| sed -n 's/.*"tag_name": *"\([^"]*\)".*/\1/p') && \
|
||||
echo "wolfssl tag: $TAG" && \
|
||||
|
||||
@ -3,6 +3,10 @@
|
||||
#
|
||||
# add -DWITH_ODBC to CFLAGS and -lodbc to LIBS to compile with ODBC
|
||||
# library support. Add -DSAFESQL for poorely written ODBC library / drivers.
|
||||
#
|
||||
# Linux splice() support is not built by default, it is slower than the
|
||||
# read/write path for most traffic. Add -DWITHSPLICE to CFLAGS to build it,
|
||||
# it must additionally be enabled per service with the -s option.
|
||||
|
||||
BUILDDIR = ../bin/
|
||||
PREFIX ?= 3proxy_
|
||||
@ -10,7 +14,7 @@ CRYPT_PREFIX ?= $(PREFIX)
|
||||
CC ?= gcc
|
||||
|
||||
CFLAGS ?= -O3 -flto
|
||||
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
|
||||
CFLAGS += -fno-strict-aliasing -c -pthread -D_GNU_SOURCE -DGETHOSTBYNAME_R -D_THREAD_SAFE -D_REENTRANT -DFD_SETSIZE=4096 -DWITH_POLL -DWITH_NETFILTER -D WITH_UN
|
||||
COUT = -o
|
||||
LN ?= ${CC}
|
||||
DCFLAGS ?= -fPIC
|
||||
|
||||
@ -8,7 +8,7 @@ BUILDDIR = ../bin/
|
||||
PREFIX = 3proxy_
|
||||
CRYPT_PREFIX = 3proxy_
|
||||
CC = cl
|
||||
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)
|
||||
CFLAGS = /nologo /Ox /MT /D "NOIPV6" /D "NO_UN" /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
|
||||
LN = link
|
||||
LDFLAGS = /nologo /subsystem:console /incremental:no
|
||||
|
||||
@ -18,6 +18,9 @@ https://github.com/3proxy/3proxy/releases
|
||||
https://hub.docker.com/r/3proxy/3proxy
|
||||
https://github.com/3proxy/3proxy/pkgs/container/3proxy
|
||||
|
||||
> [!TIP]
|
||||
> An alternative Docker image (community-maintained) with support for configuration through environment variables and a ready-to-use Helm chart for Kubernetes can be found here: [tarampampam/3proxy-docker](https://github.com/tarampampam/3proxy-docker).
|
||||
|
||||
### Archive of old versions
|
||||
|
||||
https://github.com/z3APA3A/3proxy-archive
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
|
||||
<H2><A href="howtoe.html">See HowTo:</a></H2>
|
||||
<H2><A href="howtoe.html">See HowTo:</a></h2>
|
||||
@ -1,2 +1,2 @@
|
||||
|
||||
<H2><A href="howtoe.html">См. HowTo</a></H2>
|
||||
<H2><A href="howtoe.html">См. HowTo</a></h2>
|
||||
@ -5,8 +5,8 @@
|
||||
<h4>Configuring 'maxconn'</h4>
|
||||
|
||||
The number of simultaneous connections per service is limited by the 'maxconn' option.
|
||||
The default maxconn value since 3proxy 0.8 is 500. You may want to set 'maxconn'
|
||||
to a higher value. Under this configuration:
|
||||
The default maxconn value is 500. You may want to set 'maxconn'
|
||||
to a higher value; it must be set before the services it should apply to. Under this configuration:
|
||||
<pre>
|
||||
maxconn 1000
|
||||
proxy -p3129
|
||||
@ -19,6 +19,10 @@ simultaneous connections to 3proxy.
|
||||
<p>Avoid setting 'maxconn' to an arbitrarily high value; it should be carefully
|
||||
chosen to protect the system and proxy from resource exhaustion. Setting maxconn
|
||||
above available resources can lead to denial of service conditions.
|
||||
<p>'maxconn' is not reduced automatically to fit the open file limit. If the limit is
|
||||
too low 3proxy only prints a warning at startup
|
||||
("current open file ulimits are too low") and then fails to accept connections once
|
||||
the limit is reached, so check for this warning after changing 'maxconn'.
|
||||
<h4>Understanding Resource Requirements</h4>
|
||||
Each running service requires:
|
||||
<ul>
|
||||
@ -30,10 +34,7 @@ Each connected client requires:
|
||||
<ul>
|
||||
<li>1 thread (process)
|
||||
<li>2 sockets (file descriptors). For FTP, 4 sockets are required.
|
||||
<br>Under Linux since 0.9, splice() is used. It's much more efficient but requires
|
||||
<br>2 sockets (file descriptors) + 2 pipes (file descriptors) = 4 file descriptors.
|
||||
<br>For FTP with splice(), 4 sockets and 2 pipes are required.
|
||||
<br>Up to 128K (up to 256K in the case of splice()) of kernel buffer memory. This is the theoretical maximum; actual numbers depend on connection quality and traffic amount.
|
||||
<br>Up to 128K of kernel buffer memory. This is the theoretical maximum; actual numbers depend on connection quality and traffic amount.
|
||||
<br>1 additional socket (file descriptor) during name resolution for non-cached names
|
||||
<br>1 additional socket during authentication or logging for RADIUS authentication or logging.
|
||||
<li>1 ephemeral port (3 ephemeral ports for FTP connections).
|
||||
@ -59,19 +60,45 @@ system "ulimit -Sa >>/tmp/3proxy.ulim.soft"
|
||||
at the beginning (before the first service is started) and at the end of the config file.
|
||||
Perform both a hard restart (i.e., kill and start the 3proxy process) and a soft restart
|
||||
by sending SIGUSR1 to the 3proxy process; check that the ulimits recorded to files match your
|
||||
expectations. In systemd-based distros (e.g., latest Debian/Ubuntu), changing limits.conf
|
||||
is not enough; limits must be adjusted in the systemd configuration, e.g., by setting:
|
||||
expectations. In systemd-based distros (e.g., latest Debian/Ubuntu) changing limits.conf is not
|
||||
enough for a service: limits must be set in the unit file. Set them in the 3proxy
|
||||
unit itself rather than globally, so the rest of the system is unaffected. The
|
||||
shipped 3proxy.service already contains:
|
||||
<pre>
|
||||
DefaultLimitDATA=infinity
|
||||
DefaultLimitSTACK=infinity
|
||||
DefaultLimitCORE=infinity
|
||||
DefaultLimitRSS=infinity
|
||||
DefaultLimitNOFILE=102400
|
||||
DefaultLimitAS=infinity
|
||||
DefaultLimitNPROC=10240
|
||||
DefaultLimitMEMLOCK=infinity
|
||||
LimitNOFILE=1048576
|
||||
LimitNPROC=infinity
|
||||
TasksMax=infinity
|
||||
</pre>
|
||||
To change them on an installed system use an override instead of editing the unit:
|
||||
<pre>
|
||||
systemctl edit 3proxy
|
||||
systemctl daemon-reload && systemctl restart 3proxy
|
||||
systemctl show 3proxy -p LimitNOFILE -p LimitNPROC -p TasksMax
|
||||
</pre>
|
||||
<b>TasksMax is the one that is easy to miss.</b> It is the cgroup limit on the number
|
||||
of threads, and if it is not set the unit inherits DefaultTasksMax, which is 15% of
|
||||
kernel.threads-max (about 9000 on a typical host). Since 3proxy uses one thread per
|
||||
connection, that caps concurrent connections at that number regardless of LimitNPROC
|
||||
and maxconn, and the only symptom is "pthread_create()" errors in the log.
|
||||
<p>On systemd older than 227, which has no TasksMax, and for limits that must apply to
|
||||
several services, the same values can be set globally as DefaultLimitNOFILE /
|
||||
DefaultLimitNPROC in /etc/systemd/system.conf, but prefer the per-unit settings.
|
||||
|
||||
<p>With SysV init the limits are not applied by limits.conf either, because
|
||||
start-stop-daemon does not open a PAM session, so the daemon simply inherits the limits
|
||||
of init. The shipped init script raises them itself before starting 3proxy:
|
||||
<pre>
|
||||
ulimit -n 65536
|
||||
ulimit -u 32768
|
||||
</pre>
|
||||
adjust these values in the script to match 'maxconn'.
|
||||
|
||||
<p>On FreeBSD rc.subr applies limits(1) with the login class of the service (the
|
||||
"daemon" class by default), so the limits can be set either in /etc/login.conf for that
|
||||
class, or per service in rc.conf:
|
||||
<pre>
|
||||
3proxy_limits="-n 65536"
|
||||
</pre>
|
||||
in user.conf / system.conf
|
||||
|
||||
<h4>Extending System Limitations</h4>
|
||||
|
||||
@ -86,19 +113,172 @@ proxy -olSO_REUSEADDR,SO_REUSEPORT -ocTCP_TIMESTAMPS,TCP_NODELAY -osTCP_NODELAY
|
||||
</pre>
|
||||
Available options are system-dependent.
|
||||
|
||||
<h4>Linux Tuning Hints</h4>
|
||||
|
||||
Values below are examples, not recommendations: check the current value first
|
||||
(<tt>sysctl NAME</tt>), change only what your workload actually hits, and make changes
|
||||
persistent in <tt>/etc/sysctl.d/</tt>. Defaults given in parentheses are from a recent
|
||||
(6.x) kernel and vary between distributions and versions.
|
||||
|
||||
<p><b>File descriptors.</b> 3proxy needs 2 descriptors per connection (4 for FTP), plus
|
||||
one per service, plus temporary ones for name resolution and RADIUS.
|
||||
<pre>
|
||||
fs.nr_open = 1048576 # (1048576) upper bound for any process' RLIMIT_NOFILE
|
||||
</pre>
|
||||
<tt>ulimit -n</tt> (RLIMIT_NOFILE) is the limit that actually applies and is commonly
|
||||
left at 1024; it must be raised for the 3proxy process itself, see "Setting ulimits"
|
||||
above. <tt>fs.file-max</tt> is effectively unlimited on 64-bit kernels and rarely needs
|
||||
changing.
|
||||
|
||||
<p><b>Threads.</b> Because of the "one connection - one thread" model these limits are
|
||||
reached earlier with 3proxy than with event-driven servers. Each thread also consumes
|
||||
one or two mappings, so <tt>vm.max_map_count</tt> matters too.
|
||||
<pre>
|
||||
kernel.threads-max = 200000 # (~60000 on a 16G host, scales with RAM)
|
||||
kernel.pid_max = 4194304 # (4194304)
|
||||
vm.max_map_count = 1048576 # (1048576)
|
||||
</pre>
|
||||
RLIMIT_NPROC (<tt>ulimit -u</tt>) limits threads per user and must be raised as well.
|
||||
Check the actual thread count with <tt>grep Threads /proc/PID/status</tt>.
|
||||
|
||||
<p><b>Listen queue.</b> 3proxy uses a listen backlog of 1+(maxconn/8) unless the
|
||||
'backlog' command is given, so a large 'maxconn' does not automatically give a large
|
||||
queue, and the kernel caps it at somaxconn:
|
||||
<pre>
|
||||
net.core.somaxconn = 4096 # (4096)
|
||||
net.ipv4.tcp_max_syn_backlog = 4096 # (512) raise for bursty connection rates
|
||||
net.ipv4.tcp_syncookies = 1 # (1) keep enabled
|
||||
</pre>
|
||||
|
||||
<p><b>Ephemeral ports and TIME_WAIT.</b> See "Extending the Ephemeral Port Range" above
|
||||
for the multi-IP case. The range gives about 28000 outgoing connections per
|
||||
destination address by default:
|
||||
<pre>
|
||||
net.ipv4.ip_local_port_range = 10240 65535 # (32768 60999)
|
||||
net.ipv4.tcp_tw_reuse = 2 # (2) reuse TIME_WAIT for outgoing connections
|
||||
net.ipv4.tcp_fin_timeout = 30 # (60)
|
||||
</pre>
|
||||
Do not enable tcp_tw_recycle; it was removed in kernel 4.12 and breaks NAT clients.
|
||||
|
||||
<p><b>Socket buffers.</b> Autotuning is usually right. Buffer memory is per connection,
|
||||
so raising the maximums with tens of thousands of connections costs a lot of RAM:
|
||||
<pre>
|
||||
net.core.rmem_max = 4194304 # (212992)
|
||||
net.core.wmem_max = 4194304 # (212992)
|
||||
net.ipv4.tcp_rmem = 4096 131072 6291456 # (same) min default max
|
||||
net.ipv4.tcp_wmem = 4096 16384 4194304 # (same)
|
||||
</pre>
|
||||
Raise these only for high bandwidth-delay product links, and prefer raising the third
|
||||
(max) value and leaving the default alone.
|
||||
|
||||
<p><b>Conntrack.</b> Only relevant if netfilter/nftables tracks the proxy's traffic. If
|
||||
it does, the table is exhausted long before 3proxy's own limits, with
|
||||
"nf_conntrack: table full, dropping packet" in dmesg:
|
||||
<pre>
|
||||
net.netfilter.nf_conntrack_max = 1048576
|
||||
net.netfilter.nf_conntrack_buckets = 262144
|
||||
net.netfilter.nf_conntrack_tcp_timeout_established = 3600 # (432000, i.e. 5 days)
|
||||
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 30 # (120)
|
||||
</pre>
|
||||
nf_conntrack_max defaults to nf_conntrack_buckets, which itself is derived from the
|
||||
amount of RAM, so it is often much lower than expected on small machines. Each
|
||||
connection takes two entries (one per direction). The default established timeout of
|
||||
5 days matters more than the table size with high connection churn: entries for
|
||||
connections that are long gone keep occupying the table.
|
||||
<p>If no rules need conntrack, not loading it at all is faster: the modules are loaded
|
||||
on demand by the first rule that needs them ("-m state", "-m conntrack", any NAT
|
||||
rule), so a ruleset without such rules keeps the proxy traffic untracked. If conntrack
|
||||
is needed for other traffic but not for the proxy's, exempt the proxy's traffic
|
||||
explicitly in the raw table:
|
||||
<pre>
|
||||
iptables -t raw -A PREROUTING -p tcp --dport 3128 -j CT --notrack
|
||||
iptables -t raw -A OUTPUT -p tcp -m owner --uid-owner proxy -j CT --notrack
|
||||
</pre>
|
||||
|
||||
<p><b>Conntrack helpers (ALGs).</b> The helper modules - nf_conntrack_ftp,
|
||||
nf_conntrack_sip, nf_conntrack_h323, nf_conntrack_pptp, nf_conntrack_irc,
|
||||
nf_conntrack_tftp - inspect the payload of every matching packet and create additional
|
||||
"expectation" entries, so they cost both CPU and table space, and they have a long
|
||||
history of security issues. Unload and blacklist the ones you do not actually need:
|
||||
<pre>
|
||||
lsmod | grep nf_conntrack
|
||||
modprobe -r nf_conntrack_sip nf_conntrack_h323 nf_conntrack_ftp nf_conntrack_pptp
|
||||
echo "blacklist nf_conntrack_sip" >> /etc/modprobe.d/no-alg.conf
|
||||
</pre>
|
||||
On current kernels a helper only acts when it is attached explicitly
|
||||
("-j CT --helper ftp"), so simply not attaching it is enough; automatic helper
|
||||
assignment was deprecated and later removed. Older kernels, and most router firmware,
|
||||
still enable them by default.
|
||||
|
||||
<p><b>Checking the result.</b> <tt>ss -s</tt> for socket state totals,
|
||||
<tt>ss -lnt</tt> for listen queue overflow, <tt>nstat -az TcpExtListenOverflows
|
||||
TcpExtListenDrops</tt> for accept queue drops, and
|
||||
<tt>cat /proc/PID/limits</tt> for the limits actually applied to the running process.
|
||||
|
||||
<h4>Windows Tuning Hints</h4>
|
||||
|
||||
<p><b>Dynamic (ephemeral) port range.</b> Since Windows Vista / Server 2008 the default
|
||||
range is 49152-65535, i.e. only 16384 outgoing connections per local address, which is
|
||||
reached quickly by a busy proxy. Show and change it with:
|
||||
<pre>
|
||||
netsh int ipv4 show dynamicport tcp
|
||||
netsh int ipv4 set dynamicport tcp start=10000 num=55535
|
||||
</pre>
|
||||
The minimum start port is 1025, the minimum size of the range is 255, and the end of
|
||||
the range cannot exceed 65535. The range is set separately for TCP and UDP, and for
|
||||
IPv4 and IPv6. On pre-Vista systems the equivalent is the MaxUserPort registry value
|
||||
in HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters.
|
||||
|
||||
<p><b>Listening socket.</b> 3proxy sets SO_REUSEADDR on the listening socket by
|
||||
default on Unix, but not on Windows: there it is not needed to rebind the port, and it
|
||||
only allows another local process to bind the same address and port, with undefined
|
||||
behaviour as to which of them receives the connections. If the machine is shared or
|
||||
untrusted, harden the listening socket instead:
|
||||
<pre>
|
||||
proxy -olSO_EXCLUSIVEADDRUSE
|
||||
</pre>
|
||||
Note that a socket with SO_EXCLUSIVEADDRUSE may not be immediately rebindable after a
|
||||
restart if accepted connections are still active, so test restarts before using it.
|
||||
|
||||
<p><b>Port reuse.</b> 3proxy always binds the outgoing socket before connecting, so
|
||||
Windows does not apply its automatic ephemeral port reuse (which it does only for
|
||||
connections with an implicit bind). Setting the option explicitly on the
|
||||
proxy-to-server socket therefore helps against port exhaustion:
|
||||
<pre>
|
||||
proxy -osSO_REUSE_UNICASTPORT
|
||||
</pre>
|
||||
SO_REUSE_UNICASTPORT requires Windows 10 / Server 2019 or later. On older systems
|
||||
(Windows 7 / Server 2008 and later) use SO_PORT_SCALABILITY instead; where both are
|
||||
available Microsoft recommends SO_REUSE_UNICASTPORT. Note that SO_REUSEADDR has
|
||||
different, weaker semantics on Windows than on Unix and allows another socket to bind
|
||||
the same address and port, so do not use it on the listening socket as a substitute.
|
||||
|
||||
<p><b>TIME_WAIT.</b> Closed connections hold their port for the TcpTimedWaitDelay
|
||||
period, set in
|
||||
HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters (DWORD, seconds). The
|
||||
effective default differs between Windows versions (2 to 4 minutes); check the current
|
||||
behaviour before changing it, and lower it only together with an extended port range.
|
||||
Count the connections in that state with:
|
||||
<pre>
|
||||
netstat -ano -p tcp | find /c "TIME_WAIT"
|
||||
</pre>
|
||||
|
||||
<p><b>Threads and address space.</b> Windows has no ulimit equivalent, and the handle
|
||||
count is not normally the limit. On 32-bit builds the 2 GB of user address space is:
|
||||
each connection thread reserves its stack there, so a few thousand connections can
|
||||
exhaust the address space while physical memory is still free. Use a 64-bit build for high load, and
|
||||
see "Setting Stack Size" above.
|
||||
|
||||
<p><b>Filter drivers.</b> Antivirus, endpoint protection and other LSP/WFP filter
|
||||
drivers inspect every connection and are frequently the actual bottleneck on Windows,
|
||||
costing far more than any tuning above can recover. Exclude the 3proxy process and its
|
||||
ports, or test with the protection temporarily disabled to see the difference before
|
||||
tuning anything else.
|
||||
|
||||
<h4>Using 3proxy in a Virtual Environment</h4>
|
||||
|
||||
If 3proxy is used in a VPS environment, there can be additional limitations.
|
||||
For example, kernel resources, system CPU usage, and IOCTLs can be limited differently, and this can become a bottleneck.
|
||||
Since 0.9-devel, 3proxy uses splice() by default on Linux. splice() prevents network traffic from being copied from
|
||||
kernel space to the 3proxy process and generally increases throughput, especially in the case of high-volume traffic. This is especially
|
||||
true for virtual environments (it can improve throughput up to 10 times) unless there are additional kernel limitations.
|
||||
Since some work is moved to the kernel, it requires up to 2 times more kernel resources in terms of CPU, memory, and IOCTLs.
|
||||
If your hosting additionally limits kernel resources (you can see this as nearly 100% CPU usage without any real CPU activity for
|
||||
any application performing IOCTLs), use the -s0 option to disable splice() usage for a given service, e.g.:
|
||||
<pre>
|
||||
socks -s0
|
||||
</pre>
|
||||
|
||||
<h4>Extending the Ephemeral Port Range</h4>
|
||||
|
||||
@ -184,6 +364,39 @@ randomly fail due to IP+port pair collisions if the remote or local system
|
||||
doesn't support this trick.
|
||||
</ol>
|
||||
|
||||
<h4>NAT on the Path Must Be Tuned Too</h4>
|
||||
|
||||
Everything above tunes the machine 3proxy runs on. If the outgoing traffic passes
|
||||
through NAT - a router, a firewall, a CGNAT of the provider, or a cloud NAT gateway -
|
||||
that device keeps its own translation table and its own pool of source ports, and it
|
||||
limits the number of connections independently of the proxy. Extending
|
||||
ip_local_port_range on the 3proxy host changes nothing if the NAT device rewrites the
|
||||
source port from its own, smaller pool.
|
||||
|
||||
<p>On a Linux based router the same knobs apply and have to be raised there as well:
|
||||
nf_conntrack_max / nf_conntrack_buckets and the conntrack timeouts (see "Linux Tuning
|
||||
Hints" above), plus the port range used for translation, which is ip_local_port_range
|
||||
for MASQUERADE, or the explicit range if SNAT is configured with --to-ports. Note that
|
||||
the range is per translated address: with a single public IP, all clients share it.
|
||||
|
||||
<p>Entry level and SOHO routers are the usual bottleneck here. They typically have a
|
||||
small fixed NAT/conntrack table (a few thousand entries), aggressive or non-adjustable
|
||||
timeouts, and no way to change either. Symptoms are seen on the proxy but caused by the
|
||||
router: connections that fail or hang at random under load while the proxy is far from
|
||||
its own limits, no error in the 3proxy log except a failed outgoing connect, and
|
||||
recovery after a pause or a router reboot. Before tuning 3proxy further, check the
|
||||
router's session/NAT table counters. For high load either give the proxy a public
|
||||
address without NAT in the path, or use a router where the table size and timeouts are
|
||||
configurable.
|
||||
|
||||
<p>On the router, also turn off the application layer gateways that are not actually
|
||||
used - they usually appear in the web interface as "SIP ALG", "FTP ALG", "H.323 ALG",
|
||||
"PPTP passthrough", "IPsec/VPN passthrough". They are commonly enabled by default, they
|
||||
parse the payload of matching connections, and they consume additional session table
|
||||
entries for the connections they expect. If nothing behind the proxy uses FTP, VoIP or
|
||||
those VPN protocols, disabling them frees table space and CPU on exactly the device
|
||||
that is the bottleneck.
|
||||
|
||||
<h4>Setting Stack Size</h4>
|
||||
|
||||
'stacksize' is a size added to all stack allocations and can be both positive and
|
||||
@ -199,7 +412,11 @@ the need to add additional physical memory,
|
||||
but it's system/libc dependent and requires additional testing under your
|
||||
installation. Don't forget about memory-related ulimits.
|
||||
<p>For 32-bit systems, address space can be a bottleneck you should consider. If
|
||||
you're short on address space, you can try using a negative stack size.
|
||||
you're short on address space, you can try using a negative stack size. The result is
|
||||
never lowered below the system minimum (PTHREAD_STACK_MIN), so a large negative value
|
||||
can not disable the thread stack. The base value the 'stacksize' is added to is 48K
|
||||
(64K on FreeBSD/NetBSD/OpenBSD/DragonFly, where libc uses more stack, e.g. in
|
||||
vfprintf() called by syslog()).
|
||||
|
||||
<h4>Known System Issues</h4>
|
||||
|
||||
@ -268,24 +485,6 @@ sets TCP_NODELAY for client (oc) and server (os) connections.
|
||||
<p>Do not use TCP_NODELAY on slow connections with high delays when
|
||||
connection bandwidth is a bottleneck.
|
||||
|
||||
<h4>Use Splice to Speed Up Large Data Amount Transfers</h4>
|
||||
|
||||
splice() allows copying data between connections without copying to the process
|
||||
address space. It can speed up the proxy on high-bandwidth connections if most
|
||||
connections require large data transfers. Splice is enabled by default on Linux
|
||||
since 0.9; "-s0" disables splice usage. Example:
|
||||
<pre>
|
||||
proxy -s0
|
||||
</pre>
|
||||
Splice is only available on Linux. Splice requires more system buffers and file descriptors
|
||||
and produces more IOCTLs but reduces process memory and overall CPU usage.
|
||||
Disable splice if there are a lot of short-lived connections with no bandwidth
|
||||
requirements.
|
||||
<p>Use splice only on high-speed connections (e.g., 10GbE) when the processor, memory speed, or
|
||||
system bus are bottlenecks.
|
||||
<p>TCP_NODELAY and splice are not contrary to each other and should be combined on
|
||||
high-speed connections.
|
||||
|
||||
<h4>Add Grace Delay to Reduce System Calls</h4>
|
||||
|
||||
<pre>proxy -g8000,3,10</pre>
|
||||
@ -294,7 +493,7 @@ the minimal number of packets in the same direction to apply the algorithm,
|
||||
and the last value is the delay added after polling and prior to reading data.
|
||||
The example above adds a 10-millisecond delay before reading data if the average
|
||||
polling size is below 8000 bytes and 3 read operations have been made in the same
|
||||
direction. It's especially useful with splice. <pre>logdump 1 1</pre> is useful
|
||||
direction. <pre>logdump 1 1</pre> is useful
|
||||
to see how grace delays work; choose a delay value to avoid filling the read
|
||||
pipe/buffer (typically 64K) but keep the request sizes close to the chosen average
|
||||
buffer (typically 64K) but keep the request sizes close to the chosen average
|
||||
on large file uploads/downloads.
|
||||
|
||||
@ -2,20 +2,20 @@
|
||||
<li>3APA3A 3proxy Tiny Proxy Server HowTo
|
||||
<br>Under construction, very incomplete
|
||||
<ul>
|
||||
<li><A HREF="#COMPILE">Compilation</A>
|
||||
<li><A HREF="#COMPILE">Compilation</a>
|
||||
<ul>
|
||||
<li><A HREF="#MSVC">How to compile 3proxy with Visual C++</A>
|
||||
<li><A HREF="#CMAKE">How to compile 3proxy with CMake</A>
|
||||
<li><A HREF="#GCCUNIX">How to compile 3proxy with GCC under Unix/Linux</A>
|
||||
<li><A HREF="#MSVC">How to compile 3proxy with Visual C++</a>
|
||||
<li><A HREF="#CMAKE">How to compile 3proxy with CMake</a>
|
||||
<li><A HREF="#GCCUNIX">How to compile 3proxy with GCC under Unix/Linux</a>
|
||||
</ul>
|
||||
<li><A HREF="#INSTALL">Proxy server installation and removal</A>
|
||||
<li><A HREF="#INSTALL">Proxy server installation and removal</a>
|
||||
<ul>
|
||||
<li><A HREF="#INSTNT">How to install/remove 3proxy under Windows NT/2000/XP</A>
|
||||
<li><A HREF="#INSTUNIX">How to install/remove 3proxy under Unix/Linux</A>
|
||||
<li><A HREF="#INSTMACOS">How to install/remove 3proxy under macOS</A>
|
||||
<li><A HREF="#INSTDOCKER">How to use 3proxy with Docker</A>
|
||||
<li><A HREF="#INSTNT">How to install/remove 3proxy under Windows NT/2000/XP</a>
|
||||
<li><A HREF="#INSTUNIX">How to install/remove 3proxy under Unix/Linux</a>
|
||||
<li><A HREF="#INSTMACOS">How to install/remove 3proxy under macOS</a>
|
||||
<li><A HREF="#INSTDOCKER">How to use 3proxy with Docker</a>
|
||||
</ul>
|
||||
<li><A HREF="#SERVER">Server configuration</A>
|
||||
<li><A HREF="#SERVER">Server configuration</a>
|
||||
<ul>
|
||||
<li><a href="#NOTHING">How to make 3proxy start</a></li>
|
||||
<li><a href="#LIMITS">How to make limitations (access, bandwidth, traffic, connections) work</a></li>
|
||||
@ -24,11 +24,11 @@
|
||||
<li><a href="#ODBC">How to make ODBC logging work?</a></li>
|
||||
<li><a href="#IPV6">How to make IPv6 work</a></li>
|
||||
<li><a href="#CRASH">How to fix 3proxy crashes</a></li>
|
||||
<li><A HREF="#SAMPLE">Where to find a configuration example</A>
|
||||
<li><A HREF="#LOGGING">How to set up logging</A>
|
||||
<li><A HREF="#LOGFORMAT">How to set up logging format</A>
|
||||
<li><A HREF="#LOGANALIZERS">How to use log analyzers with 3proxy</A>
|
||||
<li><A HREF="#LAUNCH">How to start any of the proxy services (HTTP, SOCKS, etc.)</A>
|
||||
<li><A HREF="#SAMPLE">Where to find a configuration example</a>
|
||||
<li><A HREF="#LOGGING">How to set up logging</a>
|
||||
<li><A HREF="#LOGFORMAT">How to set up logging format</a>
|
||||
<li><A HREF="#LOGANALIZERS">How to use log analyzers with 3proxy</a>
|
||||
<li><A HREF="#LAUNCH">How to start any of the proxy services (HTTP, SOCKS, etc.)</a>
|
||||
<li><a href="#BIND">How to bind a service to a specific interface or port</a>
|
||||
<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>
|
||||
@ -37,39 +37,39 @@
|
||||
<li><a href="#SSLPLUGIN">How to set up TLS/SSL (https proxy, mTLS)</a></li>
|
||||
<li><a href="#CERTIFICATES">How to create CA and certificates for SSL</a></li>
|
||||
<li><a href="#PCRE">How to use PCRE filtering (regular expressions)</a></li>
|
||||
<li><A HREF="#AUTH">How to limit service access</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="#REDIR">How to manage redirections</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="#ACL">How to limit user access to resources</a>
|
||||
<li><A HREF="#REDIR">How to manage redirections</a>
|
||||
<li><a href="#SOCKSREDIR">How to manage local redirections</a>
|
||||
<li><A HREF="#ROUNDROBIN">How to balance traffic between multiple external channels?</A>
|
||||
<li><A HREF="#CHAIN">How to manage proxy chains</A>
|
||||
<li><A HREF="#BANDLIM">How to limit bandwidth</A>
|
||||
<li><A HREF="#TRAFLIM">How to limit traffic amount</A>
|
||||
<li><A HREF="#ROUNDROBIN">How to balance traffic between multiple external channels?</a>
|
||||
<li><A HREF="#CHAIN">How to manage proxy chains</a>
|
||||
<li><A HREF="#BANDLIM">How to limit bandwidth</a>
|
||||
<li><A HREF="#TRAFLIM">How to limit traffic amount</a>
|
||||
<li><a href="#TRAF">How to fix incorrect traffic accounting</a>
|
||||
<li><A HREF="#NETLIST">How to build network lists</A>
|
||||
<li><A HREF="#NETLIST">How to build network lists</a>
|
||||
<li><a href="#NSCACHING">How to configure name resolution and DNS caching</a>
|
||||
<li><a href="#IPV6">How to use IPv6</a>
|
||||
<li><a href="#CONNBACK">How to use connect back</a>
|
||||
<li><a href="#HAPROXY">How to use HAProxy PROXY protocol</a>
|
||||
<li><a href="#MAXSEG">How to set TCP maximum segment size (MSS)</a>
|
||||
</ul>
|
||||
<li><A HREF="#CLIENT">Client configuration</A>
|
||||
<li><A HREF="#ADMIN">Administering and information analysis</A>
|
||||
<li><A HREF="#CLIENT">Client configuration</a>
|
||||
<li><A HREF="#ADMIN">Administering and information analysis</a>
|
||||
<ul>
|
||||
<li><A HREF="#NEWVERSION">How to obtain the latest 3proxy version</A>
|
||||
<li><A HREF="#NTSERVICE">How to control the 3proxy service under Windows NT/2000/XP</A>
|
||||
<li><A HREF="#ERRORS">Log error codes reference</A>
|
||||
<li><A HREF="#NEWVERSION">How to obtain the latest 3proxy version</a>
|
||||
<li><A HREF="#NTSERVICE">How to control the 3proxy service under Windows NT/2000/XP</a>
|
||||
<li><A HREF="#ERRORS">Log error codes reference</a>
|
||||
</ul>
|
||||
<li><A HREF="#QUEST">How to ask a question not in How To?</A>
|
||||
<li><A HREF="#QUEST">How to ask a question not in How To?</a>
|
||||
</ul>
|
||||
<br>
|
||||
<ul>
|
||||
<hr>
|
||||
<li><A NAME="COMPILE">Compilation</A>
|
||||
<li><A NAME="COMPILE">Compilation</a>
|
||||
<p>
|
||||
<ul>
|
||||
<li><A NAME="MSVC">How to compile 3proxy with Visual C++</A>
|
||||
<li><A NAME="MSVC">How to compile 3proxy with Visual C++</a>
|
||||
<p>
|
||||
Extract source code files from 3proxy.tgz (with WinZip or another utility) or use git.
|
||||
|
||||
@ -78,7 +78,7 @@ nmake /f Makefile.msvc
|
||||
</pre>
|
||||
Binaries will be placed in the <code>bin/</code> directory.
|
||||
</p>
|
||||
<li><A NAME="CMAKE">How to compile 3proxy with CMake</A>
|
||||
<li><A NAME="CMAKE">How to compile 3proxy with CMake</a>
|
||||
<p>
|
||||
CMake provides a cross-platform build system. It works on Windows (MSVC, MinGW), Linux, macOS, and BSD.
|
||||
<br>Basic build steps:
|
||||
@ -100,7 +100,7 @@ cmake -D3PROXY_USE_OPENSSL=ON -D3PROXY_USE_PCRE2=ON ..
|
||||
Available options: 3PROXY_USE_OPENSSL, 3PROXY_USE_PCRE2, 3PROXY_USE_PAM, 3PROXY_USE_ODBC.
|
||||
<br>Binaries will be placed in the <code>build/bin/</code> directory.
|
||||
</p>
|
||||
<li><A NAME="GCCUNIX">How to compile 3proxy with GCC under Unix/Linux</A></li>
|
||||
<li><A NAME="GCCUNIX">How to compile 3proxy with GCC under Unix/Linux</a></li>
|
||||
<p>
|
||||
For Linux, use:
|
||||
<pre>
|
||||
@ -121,14 +121,14 @@ and add the ODBC library to the linker variable.
|
||||
</p>
|
||||
</ul>
|
||||
<hr>
|
||||
<li><A NAME="INSTALL">Proxy server installation and removal</A>
|
||||
<li><A NAME="INSTALL">Proxy server installation and removal</a>
|
||||
<p>
|
||||
<ul>
|
||||
<li><A NAME="INSTNT">How to install/remove 3proxy under Windows NT/2000/XP</A>
|
||||
<li><A NAME="INSTNT">How to install/remove 3proxy under Windows NT/2000/XP</a>
|
||||
<p>
|
||||
Unpack 3proxy.zip to any directory, for example
|
||||
c:\Program Files\3proxy. If needed, create a directory for storing log files,
|
||||
ODBC sources, etc. Create 3proxy.cfg in the 3proxy installation directory (see <A HREF="#SERVER">Server configuration</A>).
|
||||
ODBC sources, etc. Create 3proxy.cfg in the 3proxy installation directory (see <A HREF="#SERVER">Server configuration</a>).
|
||||
Now, start a command prompt (cmd.exe).
|
||||
Change to the 3proxy installation directory and run 3proxy.exe --install:
|
||||
<pre>
|
||||
@ -148,10 +148,10 @@ C:\Program Files\3proxy>3proxy.exe --remove
|
||||
</pre>
|
||||
Now you can simply remove the 3proxy installation directory.
|
||||
</p>
|
||||
<li><A NAME="INSTUNIX">How to install/remove 3proxy under Unix/Linux</A>
|
||||
<li><A NAME="INSTUNIX">How to install/remove 3proxy under Unix/Linux</a>
|
||||
<p>
|
||||
<b>Using Makefile:</b>
|
||||
<br>Compile 3proxy (see <A HREF="#COMPILE">Compilation</A>) then run:
|
||||
<br>Compile 3proxy (see <A HREF="#COMPILE">Compilation</a>) then run:
|
||||
<pre>
|
||||
sudo make install
|
||||
</pre>
|
||||
@ -186,7 +186,7 @@ sudo systemctl enable 3proxy
|
||||
sudo systemctl start 3proxy
|
||||
</pre>
|
||||
</p>
|
||||
<li><A NAME="INSTMACOS">How to install/remove 3proxy under macOS</A>
|
||||
<li><A NAME="INSTMACOS">How to install/remove 3proxy under macOS</a>
|
||||
<p>
|
||||
<b>Using CMake (recommended):</b>
|
||||
<pre>
|
||||
@ -216,22 +216,22 @@ This installs binaries to <code>/usr/local/3proxy/bin/</code> and configuration
|
||||
<b>Service management with launchd:</b>
|
||||
<br>After installation via cmake, the service can be managed with launchctl:
|
||||
<pre>
|
||||
# Load and start the service
|
||||
# Load and start the service
|
||||
sudo launchctl load /Library/LaunchDaemons/org.3proxy.3proxy.plist
|
||||
|
||||
# Stop the service
|
||||
# Stop the service
|
||||
sudo launchctl stop org.3proxy.3proxy
|
||||
|
||||
# Start the service
|
||||
# Start the service
|
||||
sudo launchctl start org.3proxy.3proxy
|
||||
|
||||
# Unload and disable the service
|
||||
# Unload and disable the service
|
||||
sudo launchctl unload /Library/LaunchDaemons/org.3proxy.3proxy.plist
|
||||
</pre>
|
||||
The service runs as user <code>proxy</code> (created during installation).
|
||||
Configuration file: <code>/etc/3proxy/3proxy.cfg</code>
|
||||
</p>
|
||||
<li><A NAME="INSTDOCKER">How to use 3proxy with Docker</A>
|
||||
<li><A NAME="INSTDOCKER">How to use 3proxy with Docker</a>
|
||||
<p>
|
||||
<b>Using pre-built images from GitHub Container Registry:</b>
|
||||
<pre>
|
||||
@ -264,7 +264,7 @@ For non-chroot execution, mount config to <code>/etc/3proxy</code>.
|
||||
</p>
|
||||
</ul>
|
||||
<hr>
|
||||
<li><A NAME="SERVER">Server configuration</A>
|
||||
<li><A NAME="SERVER">Server configuration</a>
|
||||
<p>
|
||||
<ul>
|
||||
<li><a name="NOTHING">How to make 3proxy start</a>
|
||||
@ -293,7 +293,7 @@ location as 3proxy.exe). For an alternative configuration file location, use
|
||||
|
||||
</ul>
|
||||
|
||||
<p><A NAME="INTEXT">How to understand internal and external</A>
|
||||
<p><A NAME="INTEXT">How to understand internal and external</a>
|
||||
<p>
|
||||
Both internal and external IPs are IPs of the host running 3proxy itself.
|
||||
This configuration option is useful in situations where 3proxy is running on a
|
||||
@ -344,15 +344,15 @@ The best solution is to enable the option to resolve hostnames via the proxy on
|
||||
The problem can be resolved with the 'stacksize' command or '-S' option starting with 3proxy 0.8.4.
|
||||
|
||||
|
||||
<li><A NAME="SAMPLE">Where to find a configuration example</A>
|
||||
<li><A NAME="SAMPLE">Where to find a configuration example</a>
|
||||
<p>
|
||||
A server configuration example, 3proxy.cfg.sample, is included in every 3proxy distribution.
|
||||
</p>
|
||||
<li><A NAME="LOGGING">How to set up logging</A>
|
||||
<li><A NAME="LOGGING">How to set up logging</a>
|
||||
<p>
|
||||
3proxy can log to stdout, a file, an ODBC datasource, or
|
||||
syslog (Unix/Linux/Cygwin only). To use ODBC under Unix/Linux, you must
|
||||
compile 3proxy with Unix ODBC libraries; see <A HREF="#COMPILE">Compilation</A>.
|
||||
compile 3proxy with Unix ODBC libraries; see <A HREF="#COMPILE">Compilation</a>.
|
||||
You can control logging from 3proxy.cfg for all services, or you can control
|
||||
logging for an individual service. For example,
|
||||
/usr/local/sbin/socks -l/var/log/socks.log starts a SOCKS proxy with logging to a file.
|
||||
@ -379,14 +379,14 @@ specify an ident for syslog logging. If the filename within the "log" command co
|
||||
log c:\3proxy\logs\%y%m%d.log D creates a file like c:\3proxy\logs\060729.log;
|
||||
the date is generated based on local time.
|
||||
<pre>
|
||||
log &connstring
|
||||
log &connstring;
|
||||
</pre>
|
||||
|
||||
specifies an ODBC connection string; connstring is in the format
|
||||
datasource,username,password (the last two are optional if the
|
||||
datasource does not require or already has authentication information).
|
||||
Also, you must specify logformat to build the SQL query to insert a record into
|
||||
the log; see <A HREF="#LOGFORMAT">How to set up logging format</A>
|
||||
the log; see <A HREF="#LOGFORMAT">How to set up logging format</a>
|
||||
</p>
|
||||
<p>
|
||||
Rotation and archiving may be set up with log, rotate, and archiver commands.
|
||||
@ -416,7 +416,7 @@ sets the rotation type. LOGTYPE may be:
|
||||
Examples are located in
|
||||
3proxy.cfg.sample
|
||||
</p>
|
||||
<li><A NAME="LOGFORMAT">How to set up logging format</A>
|
||||
<li><A NAME="LOGFORMAT">How to set up logging format</a>
|
||||
<p>
|
||||
Since version 0.3, the log format may be set with the "logformat" command.
|
||||
The first symbol of the log format specifies the format of the date and time and
|
||||
@ -437,7 +437,7 @@ sets the rotation type. LOGTYPE may be:
|
||||
<li> %U - Username ('-' if unknown).
|
||||
<li> %N - Service name (PROXY, SOCKS, POP3P, etc.)
|
||||
<li> %p - Service port
|
||||
<li> %E - Error code (see <A HREF="#ERRORS">Log error codes reference</A>)
|
||||
<li> %E - Error code (see <A HREF="#ERRORS">Log error codes reference</a>)
|
||||
<li> %C - client IP
|
||||
<li> %c - client port
|
||||
<li> %R - target IP
|
||||
@ -449,7 +449,7 @@ sets the rotation type. LOGTYPE may be:
|
||||
<li> %O - bytes sent to the target
|
||||
<li> %n - hostname from the request
|
||||
<li> %h - hops before the target (if redirection or chaining is used);
|
||||
see <A HREF="#CHAIN">How to use chains and parent proxies</A>)
|
||||
see <A HREF="#CHAIN">How to use chains and parent proxies</a>)
|
||||
<li> %T - service-specific text (for example, the requested URL). %X-YT,
|
||||
where X and Y are positive numbers, only displays fields
|
||||
(space-delimited) X to Y of the text. An example is %1-2T.
|
||||
@ -472,7 +472,7 @@ logformat "-\'+_GINSERT INTO proxystat VALUES (%t, '%c', '%U', %I)"</pre>
|
||||
<br>(no line breaks)
|
||||
<br>-\'+_ instructs to replace characters \ and ' with _
|
||||
</p>
|
||||
<li><A NAME="LOGANALIZERS">How to use log analyzers with 3proxy</A>
|
||||
<li><A NAME="LOGANALIZERS">How to use log analyzers with 3proxy</a>
|
||||
<p>
|
||||
Just make the format of 3proxy logs compatible with a format supported by your
|
||||
favorite log analyzer. Examples of compatible logformats are:
|
||||
@ -515,7 +515,7 @@ or a more compatible format without the error code:
|
||||
<p><font face="courier">
|
||||
"-""+_L%C - %U [%d/%o/%Y:%H:%M:%S %z] ""%T"" 200 %I"
|
||||
</p>
|
||||
<li><A NAME="LAUNCH">How to start any of the proxy services (HTTP, SOCKS, etc.)</A>
|
||||
<li><A NAME="LAUNCH">How to start any of the proxy services (HTTP, SOCKS, etc.)</a>
|
||||
<p>
|
||||
3proxy is distributed in 2 variants: as a set of standalone modules (proxy,
|
||||
socks, pop3p, tcppm, udppm) and as a universal proxy server. These services are
|
||||
@ -552,7 +552,7 @@ except socks, which is started with port 3129.
|
||||
All logs are in the file /var/log/3proxy.log (with daily date modification and
|
||||
rotation). The 30 most recent files are stored.
|
||||
</p>
|
||||
<li><A NAME="BIND">How to bind a service to a specific interface and port?</A>
|
||||
<li><A NAME="BIND">How to bind a service to a specific interface and port?</a>
|
||||
<p>
|
||||
The -i option specifies the internal interface; -p specifies the listening port. No spaces are
|
||||
allowed. To bind the 'proxy' service to port 8080 on interfaces 192.168.1.1
|
||||
@ -606,17 +606,17 @@ tlspr supports both: for implicit TLS the destination host is taken from SNI and
|
||||
the -X option makes tlspr speak the plaintext protocol phase with the client (greeting, STARTTLS command) before
|
||||
upgrading both sides to TLS. Example:
|
||||
</p><pre>
|
||||
# https (implicit)
|
||||
# https (implicit)
|
||||
tlspr -p443 -P443 -c1
|
||||
# imaps (implicit)
|
||||
# imaps (implicit)
|
||||
tlspr -p993 -P993 -c1
|
||||
# submissions (implicit)
|
||||
# submissions (implicit)
|
||||
tlspr -p465 -P465 -c1
|
||||
# imap STARTTLS (explicit)
|
||||
# imap STARTTLS (explicit)
|
||||
tlspr -p143 -P143 -Ximap
|
||||
# submission STARTTLS (explicit)
|
||||
# submission STARTTLS (explicit)
|
||||
tlspr -p587 -P587 -Xsmtp
|
||||
# pop3 STLS (explicit)
|
||||
# pop3 STLS (explicit)
|
||||
tlspr -p110 -P110 -Xpop3
|
||||
</pre>
|
||||
<p>
|
||||
@ -679,9 +679,7 @@ socks
|
||||
<p>
|
||||
3. Using tlspr with HTTP proxy for TLS hostname-based ACL:
|
||||
</p><pre>
|
||||
allow * * * 80
|
||||
parent 1000 http 0.0.0.0 0
|
||||
allow * * * 443
|
||||
allow * * * * HTTP_CONNECT
|
||||
parent 1000 tls 0.0.0.0 0
|
||||
deny * * blocked.example.com
|
||||
allow *
|
||||
@ -707,15 +705,15 @@ nscache 65536
|
||||
nscache6 65536
|
||||
dnspr -p53
|
||||
|
||||
# google
|
||||
# google
|
||||
nsrecord smtp.gmail.com 10.0.0.1
|
||||
nsrecord imap.gmail.com 10.0.0.1
|
||||
nsrecord pop.gmail.com 10.0.0.1
|
||||
# mail.ru
|
||||
# mail.ru
|
||||
nsrecord smtp.mail.ru 10.0.0.1
|
||||
nsrecord imap.mail.ru 10.0.0.1
|
||||
nsrecord pop.mail.ru 10.0.0.1
|
||||
# yandex.ru
|
||||
# yandex.ru
|
||||
nsrecord smtp.yandex.ru 10.0.0.1
|
||||
nsrecord imap.yandex.ru 10.0.0.1
|
||||
nsrecord pop.yandex.ru 10.0.0.1
|
||||
@ -827,10 +825,10 @@ This creates an HTTPS proxy (ssl_serv) that accepts TLS connections from clients
|
||||
<b>Creating a Certificate Authority (CA):</b>
|
||||
<br>For MITM or mTLS, you need a CA. Generate a CA private key and certificate:
|
||||
</p><pre>
|
||||
# Generate CA private key
|
||||
# Generate CA private key
|
||||
openssl genrsa -out ca.key 4096
|
||||
|
||||
# Generate CA certificate (valid for 10 years)
|
||||
# Generate CA certificate (valid for 10 years)
|
||||
openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 \
|
||||
-subj "/C=US/ST=State/L=City/O=MyOrg/CN=My CA" \
|
||||
-out ca.crt
|
||||
@ -842,15 +840,15 @@ For MITM, import ca.crt into client browsers/OS as a trusted root CA.
|
||||
<b>Creating a server certificate for https:// proxy:</b>
|
||||
<br>The server certificate must have proper Subject Alternative Names (SAN):
|
||||
</p><pre>
|
||||
# Generate server private key
|
||||
# Generate server private key
|
||||
openssl genrsa -out server.key 2048
|
||||
|
||||
# Create a certificate signing request (CSR)
|
||||
# Create a certificate signing request (CSR)
|
||||
openssl req -new -key server.key \
|
||||
-subj "/C=US/ST=State/L=City/O=MyOrg/CN=proxy.example.com" \
|
||||
-out server.csr
|
||||
|
||||
# Create extensions file for SAN
|
||||
# Create extensions file for SAN
|
||||
cat > server.ext << 'EOF'
|
||||
authorityKeyIdentifier=keyid,issuer
|
||||
basicConstraints=CA:FALSE
|
||||
@ -864,7 +862,7 @@ DNS.2 = proxy
|
||||
IP.1 = 192.168.1.100
|
||||
EOF
|
||||
|
||||
# Sign the certificate with CA
|
||||
# Sign the certificate with CA
|
||||
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \
|
||||
-CAcreateserial -out server.crt -days 365 -sha256 \
|
||||
-extfile server.ext
|
||||
@ -875,27 +873,27 @@ For a public https:// proxy, use a CA like Let's Encrypt instead of self-signed.
|
||||
<p>
|
||||
<b>Creating a client certificate for mTLS:</b>
|
||||
</p><pre>
|
||||
# Generate client private key
|
||||
# Generate client private key
|
||||
openssl genrsa -out client1.key 2048
|
||||
|
||||
# Create CSR
|
||||
# Create CSR
|
||||
openssl req -new -key client1.key \
|
||||
-subj "/C=US/ST=State/L=City/O=MyOrg/CN=client1" \
|
||||
-out client1.csr
|
||||
|
||||
# Create extensions file
|
||||
# Create extensions file
|
||||
cat > client.ext << 'EOF'
|
||||
basicConstraints=CA:FALSE
|
||||
keyUsage = digitalSignature, nonRepudiation, keyEncipherment
|
||||
extendedKeyUsage = clientAuth
|
||||
EOF
|
||||
|
||||
# Sign with CA
|
||||
# Sign with CA
|
||||
openssl x509 -req -in client1.csr -CA ca.crt -CAkey ca.key \
|
||||
-CAcreateserial -out client1.crt -days 365 -sha256 \
|
||||
-extfile client.ext
|
||||
|
||||
# Create PKCS#12 bundle for browser import
|
||||
# Create PKCS#12 bundle for browser import
|
||||
openssl pkcs12 -export -out client1.p12 \
|
||||
-inkey client1.key -in client1.crt -certfile ca.crt
|
||||
</pre>
|
||||
@ -905,15 +903,15 @@ Import client1.p12 into the client browser or OS certificate store.
|
||||
<p>
|
||||
<b>Quick setup script for development/testing:</b>
|
||||
</p><pre>
|
||||
#!/bin/sh
|
||||
# Creates CA, server, and client certificates for SSLPlugin testing
|
||||
#!/bin/sh
|
||||
# Creates CA, server, and client certificates for SSLPlugin testing
|
||||
|
||||
# CA
|
||||
# CA
|
||||
openssl genrsa -out ca.key 4096
|
||||
openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 \
|
||||
-subj "/CN=3proxy CA" -out ca.crt
|
||||
|
||||
# Server
|
||||
# Server
|
||||
openssl genrsa -out server.key 2048
|
||||
openssl req -new -key server.key -subj "/CN=localhost" -out server.csr
|
||||
cat > server.ext << 'EOF'
|
||||
@ -925,7 +923,7 @@ EOF
|
||||
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \
|
||||
-CAcreateserial -out server.crt -days 365 -sha256 -extfile server.ext
|
||||
|
||||
# Client
|
||||
# Client
|
||||
openssl genrsa -out client.key 2048
|
||||
openssl req -new -key client.key -subj "/CN=client" -out client.csr
|
||||
cat > client.ext << 'EOF'
|
||||
@ -982,13 +980,13 @@ matches the connection data.
|
||||
<p>
|
||||
<b>Examples:</b>
|
||||
</p><pre>
|
||||
# Block requests containing specific keywords for certain users
|
||||
# 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
|
||||
# Block responses with specific content type
|
||||
pcre srvheader deny "Content-type: application"
|
||||
|
||||
# Replace content in both directions (censorship)
|
||||
# Replace content in both directions (censorship)
|
||||
pcre_rewrite clidata,srvdata dunno "porn|sex|pussy" "***" baduser
|
||||
pcre_extend deny * 192.168.0.1/16
|
||||
</pre>
|
||||
@ -996,11 +994,11 @@ pcre_extend deny * 192.168.0.1/16
|
||||
<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>
|
||||
First, always specify the internal interface to accept incoming connections with the
|
||||
'internal' configuration command or '-i' service command. (See
|
||||
<A HREF="#LAUNCH">How to start any of the proxy services (HTTP, SOCKS, etc.)</A>). If
|
||||
<A HREF="#LAUNCH">How to start any of the proxy services (HTTP, SOCKS, etc.)</a>). If
|
||||
no internal interface is specified, your proxy will act as an open proxy.
|
||||
<p>It's also important to specify the external interface to prevent access to the
|
||||
internal network with 'external' or -e.
|
||||
@ -1042,7 +1040,7 @@ socks
|
||||
|
||||
It's possible to authorize access by client IP address, IP address or requested resource,
|
||||
target port, time, etc., after authentication.
|
||||
(See <A HREF="#ACL">How to limit resource access</A>).
|
||||
(See <A HREF="#ACL">How to limit resource access</a>).
|
||||
</p><p>Since version 0.6, double authentication is possible, e.g.:
|
||||
<pre>
|
||||
auth iponly strong
|
||||
@ -1081,7 +1079,7 @@ critical resources, such as web administration.
|
||||
auth cache strong</pre>
|
||||
the user will not be able to use more than a single IP during the cache time (120 sec).
|
||||
</p>
|
||||
<li><A NAME="USERS">How to create a user list</A>
|
||||
<li><A NAME="USERS">How to create a user list</a>
|
||||
<p>
|
||||
The user list is created with the 'users' command.
|
||||
<pre>
|
||||
@ -1120,7 +1118,7 @@ It's possible to create NT and crypt passwords with the 3proxy_crypt utility inc
|
||||
in the distribution.
|
||||
<br>The user list is system-wide. To manage user access to a specific service, use ACLs.
|
||||
</p>
|
||||
<li><A NAME="ACL">How to limit user access to resources</A>
|
||||
<li><A NAME="ACL">How to limit user access to resources</a>
|
||||
<p>
|
||||
The commands allow, deny, and flush are used to manage ACLs:
|
||||
<p><font face="courier">
|
||||
@ -1132,7 +1130,7 @@ allow <userlist> <sourcelist> <targetlist> <targetportlist&
|
||||
The 'flush' command is used to finish with the existing ACL and start a new one.
|
||||
It's required to have different ACLs for different services.
|
||||
'allow' is used to allow a connection, and 'deny' to deny a connection. The 'allow'
|
||||
command can be extended by the 'parent' command to manage redirections (see <A href="#REDIR">How to manage redirections</A>). If the ACL
|
||||
command can be extended by the 'parent' command to manage redirections (see <A href="#REDIR">How to manage redirections</a>). If the ACL
|
||||
is empty, it allows everything. If the ACL is not empty, the first matching ACL entry
|
||||
is searched for the user request, and the ACL action (allow or deny) is performed. If
|
||||
no matching record is found, the connection is denied, and the user will be asked to
|
||||
@ -1180,7 +1178,7 @@ add 'deny *' to the end of the list.
|
||||
* in an ACL means "any".
|
||||
Usage examples can be found in 3proxy.cfg.sample.
|
||||
</p>
|
||||
<li><A NAME="REDIR">How to manage redirections</A>
|
||||
<li><A NAME="REDIR">How to manage redirections</a>
|
||||
<p>
|
||||
Redirections are useful to, e.g., forward requests from specific clients
|
||||
to different servers or proxy servers. Additionally, redirections are useful
|
||||
@ -1239,22 +1237,22 @@ auth iponly
|
||||
allow * * * 80,8080-8088
|
||||
parent 1000 http 0.0.0.0 0
|
||||
allow * * * 80,8080-8088
|
||||
#redirect ports 80 and 8080-8088 to local HTTP proxy
|
||||
#Second allow is required, because ACLs are checked
|
||||
#twice: first time by socks and second by http proxy.
|
||||
#redirect ports 80 and 8080-8088 to local HTTP proxy
|
||||
#Second allow is required, because ACLs are checked
|
||||
#twice: first time by socks and second by http proxy.
|
||||
|
||||
allow * * * 21,2121
|
||||
parent 1000 ftp 0.0.0.0 0
|
||||
allow * * * 21,2121
|
||||
#redirect ports 21 and 2121 to local
|
||||
#ftp proxy
|
||||
#redirect ports 21 and 2121 to local
|
||||
#ftp proxy
|
||||
|
||||
|
||||
allow *
|
||||
#allow the rest of connections directly
|
||||
#allow the rest of connections directly
|
||||
|
||||
socks
|
||||
#now let the socks server start
|
||||
#now let the socks server start
|
||||
</pre>
|
||||
|
||||
<p><i>Q: How does it affect different ACL rules?</i></p>
|
||||
@ -1262,20 +1260,20 @@ A: After local redirections, rules are applied again to the protocol-level reque
|
||||
<pre>
|
||||
allow * * * 80,8080-8088
|
||||
parent 1000 http 0.0.0.0 0
|
||||
#redirect http traffic to internal proxy
|
||||
#redirect http traffic to internal proxy
|
||||
|
||||
allow * * $c:\3proxy\local.nets 80,8080-8088
|
||||
#allow direct access to local.nets networks
|
||||
#allow direct access to local.nets networks
|
||||
allow * * * 80,8080-8088
|
||||
parent 1000 http proxy.3proxy.org 3128
|
||||
#use parent caching proxy for the rest of the networks
|
||||
#use parent caching proxy for the rest of the networks
|
||||
|
||||
allow *
|
||||
#allow direct connections for the rest of socks
|
||||
#requests
|
||||
#allow direct connections for the rest of socks
|
||||
#requests
|
||||
</pre>
|
||||
|
||||
<li><A NAME="ROUNDROBIN">How to balance traffic between multiple external channels?</A>
|
||||
<li><A NAME="ROUNDROBIN">How to balance traffic between multiple external channels?</a>
|
||||
<p>
|
||||
The proxy itself doesn't manage network-level routing. The only way to control
|
||||
the outgoing channel is to select the external interface. It's possible to make
|
||||
@ -1304,7 +1302,7 @@ for Windows:
|
||||
If you don't have a second address yet, just add it. Under Linux/Unix, it's better
|
||||
to use source routing.
|
||||
</p>
|
||||
<li><A NAME="CHAIN">How to manage proxy chains</A>
|
||||
<li><A NAME="CHAIN">How to manage proxy chains</a>
|
||||
<p>
|
||||
The parent command may also be used to build proxy chains. In this case,
|
||||
multiple 'parent' commands are used for a single 'allow' rule with different
|
||||
@ -1340,7 +1338,7 @@ the second hop is 192.168.20.1, and the 3rd one is either 192.168.30.1 with a pr
|
||||
of 30% or 192.168.40.1 with a probability of 70%.
|
||||
</p>
|
||||
|
||||
<li><A NAME="BANDLIM">How to limit bandwidth</A>
|
||||
<li><A NAME="BANDLIM">How to limit bandwidth</a>
|
||||
<p>
|
||||
3proxy supports bandwidth filters. Use the bandlimin/bandlimout and
|
||||
nobandlimin/nobandlimout commands to manage filters. 'in' means incoming and 'out' means outgoing traffic.
|
||||
@ -1370,7 +1368,7 @@ In this example:
|
||||
mail traffic from POP3 servers bypasses the pipe and has no bandwidth
|
||||
limitation.
|
||||
</p>
|
||||
<li><A NAME="TRAFLIM">How to limit traffic amount</A>
|
||||
<li><A NAME="TRAFLIM">How to limit traffic amount</a>
|
||||
<p>
|
||||
<p><font face="courier">
|
||||
counter <filename> <type> <reportpath>
|
||||
@ -1504,21 +1502,21 @@ proxy -p3128 -OcTCP_NODELAY,TCP_MAXSEG -OsTCP_NODELAY,TCP_MAXSEG
|
||||
</ul>
|
||||
|
||||
<hr>
|
||||
<li><A NAME="CLIENT">Client configuration</A>
|
||||
<li><A NAME="CLIENT">Client configuration</a>
|
||||
<p>
|
||||
<hr>
|
||||
<li><A NAME="ADMIN">Administering and information analysis</A>
|
||||
<li><A NAME="ADMIN">Administering and information analysis</a>
|
||||
<p>
|
||||
<ul>
|
||||
<li><A NAME="NEWVERSION">How to obtain latest 3proxy version</A>
|
||||
<li><A NAME="NEWVERSION">How to obtain latest 3proxy version</a>
|
||||
<p>
|
||||
The latest version of 3proxy may be obtained
|
||||
<A HREF="https://3proxy.org/">here</A>.
|
||||
<A HREF="https://3proxy.org/">here</a>.
|
||||
A new version may have changes and incompatibilities with the previous one in file
|
||||
formats or commands. Please read the CHANGELOG file and other documentation
|
||||
before installing a new version.
|
||||
</p>
|
||||
<li><A NAME="NTSERVICE">How to control 3proxy service under Windows NT/2000/XP</A>
|
||||
<li><A NAME="NTSERVICE">How to control 3proxy service under Windows NT/2000/XP</a>
|
||||
<p>
|
||||
If installed as a system service, 3proxy understands Windows service commands
|
||||
for START, STOP, PAUSE, and RESUME. If the service is PAUSEd, no new connections
|
||||
@ -1534,7 +1532,7 @@ You can control the 3proxy service via "Services" administration or via the "net
|
||||
net continue 3proxy
|
||||
</pre>
|
||||
</p>
|
||||
<li><A NAME="ERRORS">Log error codes reference</A>
|
||||
<li><A NAME="ERRORS">Log error codes reference</a>
|
||||
<p>
|
||||
<ul>
|
||||
<li>0 - Operation successfully completed (connection
|
||||
@ -1597,9 +1595,9 @@ You can control the 3proxy service via "Services" administration or via the "net
|
||||
</p>
|
||||
</ul>
|
||||
<hr>
|
||||
<li><A NAME="QUEST">How to ask a question not in How To?</A>
|
||||
<li><A NAME="QUEST">How to ask a question not in How To?</a>
|
||||
<p>
|
||||
Ask it in <A HREF="https://github.com/z3APA3A/3proxy/issues">Github</A>.
|
||||
Ask it in <A HREF="https://github.com/z3APA3A/3proxy/issues">Github</a>.
|
||||
Please read this document before asking a question.
|
||||
</ul>
|
||||
|
||||
|
||||
@ -210,16 +210,16 @@
|
||||
<b>Управление службой через launchd:</b>
|
||||
<br>После установки через cmake службой можно управлять с помощью launchctl:
|
||||
<pre>
|
||||
# Загрузить и запустить службу
|
||||
# Загрузить и запустить службу
|
||||
sudo launchctl load /Library/LaunchDaemons/org.3proxy.3proxy.plist
|
||||
|
||||
# Остановить службу
|
||||
# Остановить службу
|
||||
sudo launchctl stop org.3proxy.3proxy
|
||||
|
||||
# Запустить службу
|
||||
# Запустить службу
|
||||
sudo launchctl start org.3proxy.3proxy
|
||||
|
||||
# Выгрузить и отключить службу
|
||||
# Выгрузить и отключить службу
|
||||
sudo launchctl unload /Library/LaunchDaemons/org.3proxy.3proxy.plist</pre>
|
||||
Служба запускается от имени пользователя <code>proxy</code> (создаётся при установке).
|
||||
Файл конфигурации: <code>/etc/3proxy/3proxy.cfg</code>
|
||||
@ -388,7 +388,7 @@
|
||||
-l@ident</pre>
|
||||
соответствуют ведению журнала через syslog с идентификатором ident.
|
||||
<pre>
|
||||
log &connstring</pre>
|
||||
log &connstring;</pre>
|
||||
соответствует ведению журнала через ODBC, connstring задается в формате
|
||||
datasource,username,password (последние два параметра опциональны, если
|
||||
datasource не требует или уже содержит сведения для авторизации). При этом
|
||||
@ -614,17 +614,17 @@ tlspr поддерживает оба варианта: для implicit TLS хо
|
||||
опция -X заставляет tlspr говорить с клиентом на plaintext-фазе протокола (приветствие, команда STARTTLS) перед
|
||||
поднятием TLS с обеих сторон. Пример:
|
||||
</p><pre>
|
||||
# https (implicit)
|
||||
# https (implicit)
|
||||
tlspr -p443 -P443 -c1
|
||||
# imaps (implicit)
|
||||
# imaps (implicit)
|
||||
tlspr -p993 -P993 -c1
|
||||
# submissions (implicit)
|
||||
# submissions (implicit)
|
||||
tlspr -p465 -P465 -c1
|
||||
# imap STARTTLS (explicit)
|
||||
# imap STARTTLS (explicit)
|
||||
tlspr -p143 -P143 -Ximap
|
||||
# submission STARTTLS (explicit)
|
||||
# submission STARTTLS (explicit)
|
||||
tlspr -p587 -P587 -Xsmtp
|
||||
# pop3 STLS (explicit)
|
||||
# pop3 STLS (explicit)
|
||||
tlspr -p110 -P110 -Xpop3
|
||||
</pre>
|
||||
<p>
|
||||
@ -687,9 +687,7 @@ socks
|
||||
<p>
|
||||
3. Использование tlspr с HTTP proxy для ACL по имени хоста TLS:
|
||||
</p><pre>
|
||||
allow * * * 80
|
||||
parent 1000 http 0.0.0.0 0
|
||||
allow * * * 443
|
||||
allow * * * * HTTP_CONNECT
|
||||
parent 1000 tls 0.0.0.0 0
|
||||
deny * * blocked.example.com
|
||||
allow *
|
||||
@ -716,15 +714,15 @@ nscache 65536
|
||||
nscache6 65536
|
||||
dnspr -p53
|
||||
|
||||
# google
|
||||
# google
|
||||
nsrecord smtp.gmail.com 10.0.0.1
|
||||
nsrecord imap.gmail.com 10.0.0.1
|
||||
nsrecord pop.gmail.com 10.0.0.1
|
||||
# mail.ru
|
||||
# mail.ru
|
||||
nsrecord smtp.mail.ru 10.0.0.1
|
||||
nsrecord imap.mail.ru 10.0.0.1
|
||||
nsrecord pop.mail.ru 10.0.0.1
|
||||
# yandex.ru
|
||||
# yandex.ru
|
||||
nsrecord smtp.yandex.ru 10.0.0.1
|
||||
nsrecord imap.yandex.ru 10.0.0.1
|
||||
nsrecord pop.yandex.ru 10.0.0.1
|
||||
@ -837,10 +835,10 @@ ssl_nocli
|
||||
<b>Создание удостоверяющего центра (CA):</b>
|
||||
<br>Для MITM или mTLS требуется CA. Сгенерируйте закрытый ключ CA и сертификат:
|
||||
</p><pre>
|
||||
# Генерация закрытого ключа CA
|
||||
# Генерация закрытого ключа CA
|
||||
openssl genrsa -out ca.key 4096
|
||||
|
||||
# Генерация сертификата CA (действителен 10 лет)
|
||||
# Генерация сертификата CA (действителен 10 лет)
|
||||
openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 \
|
||||
-subj "/C=RU/ST=Region/L=City/O=MyOrg/CN=My CA" \
|
||||
-out ca.crt
|
||||
@ -852,15 +850,15 @@ openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 \
|
||||
<b>Создание серверного сертификата для https:// прокси:</b>
|
||||
<br>Серверный сертификат должен иметь правильные альтернативные имена (SAN):
|
||||
</p><pre>
|
||||
# Генерация закрытого ключа сервера
|
||||
# Генерация закрытого ключа сервера
|
||||
openssl genrsa -out server.key 2048
|
||||
|
||||
# Создание запроса на подпись сертификата (CSR)
|
||||
# Создание запроса на подпись сертификата (CSR)
|
||||
openssl req -new -key server.key \
|
||||
-subj "/C=RU/ST=Region/L=City/O=MyOrg/CN=proxy.example.com" \
|
||||
-out server.csr
|
||||
|
||||
# Создание файла расширений для SAN
|
||||
# Создание файла расширений для SAN
|
||||
cat > server.ext << 'EOF'
|
||||
authorityKeyIdentifier=keyid,issuer
|
||||
basicConstraints=CA:FALSE
|
||||
@ -874,7 +872,7 @@ DNS.2 = proxy
|
||||
IP.1 = 192.168.1.100
|
||||
EOF
|
||||
|
||||
# Подписание сертификата CA
|
||||
# Подписание сертификата CA
|
||||
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \
|
||||
-CAcreateserial -out server.crt -days 365 -sha256 \
|
||||
-extfile server.ext
|
||||
@ -885,27 +883,27 @@ openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \
|
||||
<p>
|
||||
<b>Создание клиентского сертификата для mTLS:</b>
|
||||
</p><pre>
|
||||
# Генерация закрытого ключа клиента
|
||||
# Генерация закрытого ключа клиента
|
||||
openssl genrsa -out client1.key 2048
|
||||
|
||||
# Создание CSR
|
||||
# Создание CSR
|
||||
openssl req -new -key client1.key \
|
||||
-subj "/C=RU/ST=Region/L=City/O=MyOrg/CN=client1" \
|
||||
-out client1.csr
|
||||
|
||||
# Создание файла расширений
|
||||
# Создание файла расширений
|
||||
cat > client.ext << 'EOF'
|
||||
basicConstraints=CA:FALSE
|
||||
keyUsage = digitalSignature, nonRepudiation, keyEncipherment
|
||||
extendedKeyUsage = clientAuth
|
||||
EOF
|
||||
|
||||
# Подписание CA
|
||||
# Подписание CA
|
||||
openssl x509 -req -in client1.csr -CA ca.crt -CAkey ca.key \
|
||||
-CAcreateserial -out client1.crt -days 365 -sha256 \
|
||||
-extfile client.ext
|
||||
|
||||
# Создание PKCS#12 для импорта в браузер
|
||||
# Создание PKCS#12 для импорта в браузер
|
||||
openssl pkcs12 -export -out client1.p12 \
|
||||
-inkey client1.key -in client1.crt -certfile ca.crt
|
||||
</pre>
|
||||
@ -915,15 +913,15 @@ openssl pkcs12 -export -out client1.p12 \
|
||||
<p>
|
||||
<b>Скрипт быстрой настройки для разработки/тестирования:</b>
|
||||
</p><pre>
|
||||
#!/bin/sh
|
||||
# Создаёт CA, серверный и клиентский сертификаты для тестирования SSLPlugin
|
||||
#!/bin/sh
|
||||
# Создаёт CA, серверный и клиентский сертификаты для тестирования SSLPlugin
|
||||
|
||||
# CA
|
||||
# CA
|
||||
openssl genrsa -out ca.key 4096
|
||||
openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 \
|
||||
-subj "/CN=3proxy CA" -out ca.crt
|
||||
|
||||
# Сервер
|
||||
# Сервер
|
||||
openssl genrsa -out server.key 2048
|
||||
openssl req -new -key server.key -subj "/CN=localhost" -out server.csr
|
||||
cat > server.ext << 'EOF'
|
||||
@ -935,7 +933,7 @@ EOF
|
||||
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \
|
||||
-CAcreateserial -out server.crt -days 365 -sha256 -extfile server.ext
|
||||
|
||||
# Клиент
|
||||
# Клиент
|
||||
openssl genrsa -out client.key 2048
|
||||
openssl req -new -key client.key -subj "/CN=client" -out client.csr
|
||||
cat > client.ext << 'EOF'
|
||||
@ -993,13 +991,13 @@ IP назначения, порты и т.д.), аналогичный кома
|
||||
<p>
|
||||
<b>Примеры:</b>
|
||||
</p><pre>
|
||||
# Блокировать запросы с определёнными ключевыми словами для некоторых пользователей
|
||||
# Блокировать запросы с определёнными ключевыми словами для некоторых пользователей
|
||||
pcre request deny "porn|sex" user1,user2,user3 192.168.0.0/16
|
||||
|
||||
# Блокировать ответы с определённым content-type
|
||||
# Блокировать ответы с определённым 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>
|
||||
@ -1270,16 +1268,16 @@ pcre_extend deny * 192.168.0.1/16
|
||||
allow * * * 80,8080-8088
|
||||
parent 1000 http 0.0.0.0 0
|
||||
allow * * * 80,8080-8088
|
||||
#перенаправить соединения по портам 80 и 8080-8088 в локальный
|
||||
#http прокси. Вторая команда allow необходима, т.к. контроль доступа
|
||||
#осуществляется 2 раза - на уровне socks и на уровне HTTP прокси
|
||||
#перенаправить соединения по портам 80 и 8080-8088 в локальный
|
||||
#http прокси. Вторая команда allow необходима, т.к. контроль доступа
|
||||
#осуществляется 2 раза - на уровне socks и на уровне HTTP прокси
|
||||
allow * * * 21,2121
|
||||
parent 1000 ftp 0.0.0.0 0
|
||||
allow * * * 21,2121
|
||||
#перенаправить соединения по портам 21 и 2121 в локальный
|
||||
#ftp прокси
|
||||
#перенаправить соединения по портам 21 и 2121 в локальный
|
||||
#ftp прокси
|
||||
allow *
|
||||
#пустить все соединения напрямую
|
||||
#пустить все соединения напрямую
|
||||
socks</pre>
|
||||
</p>
|
||||
<li><a name="REDIINTER"><i>Q: Как взаимодействует с другими правилами в ACL?</i></a></li>
|
||||
@ -1294,14 +1292,14 @@ pcre_extend deny * 192.168.0.1/16
|
||||
<pre>
|
||||
allow * * * 80,8080-8088
|
||||
parent 1000 http 0.0.0.0 0
|
||||
#перенаправить во внутренний прокси
|
||||
#перенаправить во внутренний прокси
|
||||
allow * * $c:\3proxy\local.nets 80,8080-8088
|
||||
#разрешить прямой web-доступ к сетям из local.nets
|
||||
#разрешить прямой web-доступ к сетям из local.nets
|
||||
allow * * * 80,8080-8088
|
||||
parent 1000 http proxy.3proxy.ru 3128
|
||||
#все остальные веб-запросы перенаправить на внешний прокси-сервер
|
||||
#все остальные веб-запросы перенаправить на внешний прокси-сервер
|
||||
allow *
|
||||
#разрешить socks-запросы по другим портам</pre>
|
||||
#разрешить socks-запросы по другим портам</pre>
|
||||
</p>
|
||||
</ul>
|
||||
<li><a name="ROUNDROBIN"><i>Как организовать балансировку между несоклькими каналами</i></a>
|
||||
|
||||
@ -192,9 +192,16 @@ or hostname, useful in case of dynamic DNS. <b><br>
|
||||
(<b>-ol</b>), connect back client (<b>-or</b>), connect back
|
||||
listening (<b>-oR</b>) sockets. Options like TCP_CORK,
|
||||
TCP_NODELAY, TCP_DEFER_ACCEPT, TCP_QUICKACK, TCP_TIMESTAMPS,
|
||||
USE_TCP_FASTOPEN, SO_REUSEADDR, SO_REUSEPORT,
|
||||
SO_PORT_SCALABILITY, SO_REUSE_UNICASTPORT, SO_KEEPALIVE,
|
||||
SO_DONTROUTE may be supported depending on OS. <b><br>
|
||||
TCP_FASTOPEN, SO_REUSEADDR, SO_REUSEPORT,
|
||||
SO_EXCLUSIVEADDRUSE, SO_PORT_SCALABILITY,
|
||||
SO_REUSE_UNICASTPORT, SO_KEEPALIVE, SO_DONTROUTE may be
|
||||
supported depending on OS. SO_REUSEADDR and SO_REUSEPORT are
|
||||
set on the listening socket by default on Unix. On Windows
|
||||
SO_REUSEADDR is not set: it is not required to rebind a
|
||||
listening port and it only lets another local process bind
|
||||
the same address and port. Use SO_EXCLUSIVEADDRUSE (Windows)
|
||||
on the listening socket (<b>-ol</b>) to prevent that.
|
||||
<b><br>
|
||||
-H</b> (for all services) Expect HAProxy PROXY protocol v1
|
||||
header on incoming connection. This allows the proxy to
|
||||
receive real client IP address from HAProxy or other load
|
||||
@ -205,9 +212,16 @@ be sent before any protocol-specific data. <b><br>
|
||||
delay GRACE_DELAY milliseconds before polling if average
|
||||
polling size is below GRACE_TRAFF bytes and GRACE_NUM read
|
||||
operations in a single direction are detected within 1
|
||||
second. Useful to minimize polling <b>-s</b> <br>
|
||||
second. Useful to minimize polling <b><br>
|
||||
-s</b> <br>
|
||||
(for admin) secure, allow only secure operations, currently
|
||||
only traffic counters view without ability to reset. <br>
|
||||
(for TCP services, Linux) enable splice(). splice() is not
|
||||
built by default and is disabled even when built, because
|
||||
current Linux does not implement SPLICE_F_MOVE, so no real
|
||||
zero-copy takes place and the read/write path is faster for
|
||||
most traffic. Rebuild with -DWITHSPLICE to make -s
|
||||
available, -s0 disables it explicitly. <br>
|
||||
(for dnspr) simple, do not use resolver and 3proxy cache,
|
||||
always use external DNS server. <br>
|
||||
(for udppm) singlepacket, expect only one packet from both
|
||||
@ -762,8 +776,8 @@ service (with -s parameter). <b><br>
|
||||
ha</b> send HAProxy PROXY protocol v1 header to the next
|
||||
parent proxy (or to the destination if <b>ha</b> is used
|
||||
alone). Place <b>ha</b> before the parent that should
|
||||
receive the header; after the header is sent, negotiation
|
||||
of that parent protocol continues (SOCKS, CONNECT, etc.).
|
||||
receive the header; after the header is sent, negotiation of
|
||||
that parent protocol continues (SOCKS, CONNECT, etc.).
|
||||
Useful for passing client IP information to the parent
|
||||
proxy. Example: <br>
|
||||
parent 1000 ha 0.0.0.0 0 <br>
|
||||
@ -1048,7 +1062,17 @@ experience 3proxy crash on request processing, try to set
|
||||
some positive value. You may start with stacksize 65536 and
|
||||
then find the minimal value for the service to work. If you
|
||||
experience memory shortage, you can try to experiment with
|
||||
negative values.</p>
|
||||
negative values. <br>
|
||||
With SQL logging (log &ODBC_string) the value is
|
||||
automatically raised to 32768 if it is smaller, because ODBC
|
||||
drivers require more stack. A <b>stacksize</b> command
|
||||
placed after the <b>log</b> command overrides this. <br>
|
||||
The base stack size the value is added to is 49152. On
|
||||
FreeBSD, NetBSD, OpenBSD and DragonFly it is 65536, because
|
||||
libc functions such as vfprintf() called by syslog() use
|
||||
significantly more stack there. The result is never lowered
|
||||
below PTHREAD_STACK_MIN, so a large negative value can not
|
||||
disable the thread stack.</p>
|
||||
|
||||
<h2>PLUGINS
|
||||
<a name="PLUGINS"></a>
|
||||
|
||||
@ -178,7 +178,8 @@ connect to given remote HOST:port instead of listening local connection on -p or
|
||||
.br
|
||||
.B -oc\fIOPTIONS\fB, -os\fIOPTIONS\fB, -ol\fIOPTIONS\fB, -or\fIOPTIONS\fB, -oR\fIOPTIONS\fR
|
||||
options for proxy-to-client (\fB-oc\fR), proxy-to-server (\fB-os\fR), proxy listening (\fB-ol\fR), connect back client (\fB-or\fR), connect back listening (\fB-oR\fR) sockets.
|
||||
Options like TCP_CORK, TCP_NODELAY, TCP_DEFER_ACCEPT, TCP_QUICKACK, TCP_TIMESTAMPS, USE_TCP_FASTOPEN, SO_REUSEADDR, SO_REUSEPORT, SO_PORT_SCALABILITY, SO_REUSE_UNICASTPORT, SO_KEEPALIVE, SO_DONTROUTE may be supported depending on OS.
|
||||
Options like TCP_CORK, TCP_NODELAY, TCP_DEFER_ACCEPT, TCP_QUICKACK, TCP_TIMESTAMPS, TCP_FASTOPEN, SO_REUSEADDR, SO_REUSEPORT, SO_EXCLUSIVEADDRUSE, SO_PORT_SCALABILITY, SO_REUSE_UNICASTPORT, SO_KEEPALIVE, SO_DONTROUTE may be supported depending on OS.
|
||||
SO_REUSEADDR and SO_REUSEPORT are set on the listening socket by default on Unix. On Windows SO_REUSEADDR is not set: it is not required to rebind a listening port and it only lets another local process bind the same address and port. Use SO_EXCLUSIVEADDRUSE (Windows) on the listening socket (\fB-ol\fR) to prevent that.
|
||||
.br
|
||||
.B -H
|
||||
(for all services) Expect HAProxy PROXY protocol v1 header on incoming connection.
|
||||
@ -188,9 +189,16 @@ any protocol-specific data.
|
||||
.br
|
||||
.B -g(\fIGRACE_TRAFF\fB,\fIGRACE_NUM\fB,\fIGRACE_DELAY\fR)
|
||||
delay GRACE_DELAY milliseconds before polling if average polling size is below GRACE_TRAFF bytes and GRACE_NUM read operations in a single direction are detected within 1 second. Useful to minimize polling
|
||||
.br
|
||||
.B -s
|
||||
(for admin) secure, allow only secure operations, currently only traffic counters
|
||||
view without ability to reset.
|
||||
.br
|
||||
(for TCP services, Linux) enable splice(). splice() is not built by default and
|
||||
is disabled even when built, because current Linux does not implement
|
||||
SPLICE_F_MOVE, so no real zero-copy takes place and the read/write path is faster
|
||||
for most traffic. Rebuild with -DWITHSPLICE to make -s available, -s0 disables it
|
||||
explicitly.
|
||||
.br
|
||||
(for dnspr) simple, do not use resolver and 3proxy cache, always use external DNS server.
|
||||
.br
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[Unit]
|
||||
Description=3proxy tiny proxy server
|
||||
Documentation=man:3proxy(1)
|
||||
Documentation=man:3proxy(8) man:3proxy.cfg(5)
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
@ -13,8 +13,15 @@ ExecReload=/bin/kill -SIGUSR1 $MAINPID
|
||||
KillMode=process
|
||||
Restart=on-failure
|
||||
RestartSec=60s
|
||||
LimitNOFILE=65536
|
||||
LimitNPROC=32768
|
||||
# 3proxy uses one thread and two descriptors per connection (four for ftppr),
|
||||
# so it reaches these limits much earlier than event driven servers. They are
|
||||
# ceilings only: the actual number of connections is governed by 'maxconn' in
|
||||
# the configuration file. TasksMax must be set explicitly, systemd's
|
||||
# DefaultTasksMax (15% of kernel.threads-max, e.g. ~9000) otherwise caps the
|
||||
# number of threads, and thus connections, regardless of LimitNPROC.
|
||||
LimitNOFILE=1048576
|
||||
LimitNPROC=infinity
|
||||
TasksMax=infinity
|
||||
RuntimeDirectory=3proxy
|
||||
RuntimeDirectoryMode=0755
|
||||
|
||||
|
||||
@ -24,9 +24,19 @@ if [ -f /etc/init.d/functions ]; then
|
||||
. /etc/init.d/functions
|
||||
fi
|
||||
|
||||
# SysV init does not apply limits.conf consistently: start-stop-daemon does not
|
||||
# open a PAM session, so pam_limits is not involved and the daemon inherits the
|
||||
# limits of init. 3proxy needs two descriptors per connection (four for ftppr),
|
||||
# so raise them here. Adjust to match 'maxconn' in the configuration file.
|
||||
set_limits() {
|
||||
ulimit -n 65536 2>/dev/null || ulimit -n 4096 2>/dev/null || true
|
||||
ulimit -u 32768 2>/dev/null || true
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
echo -n "Starting 3Proxy: "
|
||||
set_limits
|
||||
|
||||
if [ ! -d /var/run/3proxy ]; then
|
||||
mkdir -p /var/run/3proxy
|
||||
|
||||
@ -80,7 +80,7 @@ int cacheauth(struct clientparam * param){
|
||||
((type & 4) && !param->password) ||
|
||||
(
|
||||
(type & 1) && *SAFAMILY(¶m->sincr) != AF_INET
|
||||
#ifndef NOIPv6
|
||||
#ifndef NOIPV6
|
||||
&& *SAFAMILY(¶m->sincr) != AF_INET6
|
||||
#endif
|
||||
) || (!hashresolv(&auth_table, param, &ac, &ttl))) {
|
||||
@ -108,7 +108,6 @@ int cacheauth(struct clientparam * param){
|
||||
int doauth(struct clientparam * param){
|
||||
int res = 0;
|
||||
struct auth *authfuncs;
|
||||
char * tmp;
|
||||
int ret = 0;
|
||||
|
||||
for(authfuncs=param->srv->authfuncs; authfuncs; authfuncs=authfuncs->next){
|
||||
@ -125,7 +124,7 @@ int doauth(struct clientparam * param){
|
||||
ac.username[63] = 0;
|
||||
}
|
||||
if(*SAFAMILY(¶m->sincr) == AF_INET
|
||||
#ifndef NOIPv6
|
||||
#ifndef NOIPV6
|
||||
|| *SAFAMILY(¶m->sincr) == AF_INET6
|
||||
#endif
|
||||
) {
|
||||
@ -134,7 +133,7 @@ int doauth(struct clientparam * param){
|
||||
}
|
||||
|
||||
if(*SAFAMILY(¶m->sinsl) == AF_INET
|
||||
#ifndef NOIPv6
|
||||
#ifndef NOIPV6
|
||||
|| *SAFAMILY(¶m->sinsl) == AF_INET6
|
||||
#endif
|
||||
) {
|
||||
@ -235,7 +234,6 @@ static int ctstrcmp(const char *a, const char *b, size_t maxlen){
|
||||
}
|
||||
|
||||
int strongauth(struct clientparam * param){
|
||||
static char dummy;
|
||||
unsigned char buf[256];
|
||||
char pass[256] = {0};
|
||||
|
||||
|
||||
@ -174,17 +174,6 @@ void md5_calc(unsigned char *output, unsigned char *input,
|
||||
unsigned int inputlen);
|
||||
|
||||
|
||||
char *strNcpy(char *dest, const char *src, int n)
|
||||
{
|
||||
if (n > 0)
|
||||
strncpy(dest, src, n);
|
||||
else
|
||||
n = 1;
|
||||
dest[n - 1] = 0;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
void md5_calc(unsigned char *output, unsigned char *input,
|
||||
unsigned int inlen)
|
||||
{
|
||||
@ -308,14 +297,12 @@ int radsend(struct clientparam * param, int auth, int stop){
|
||||
unsigned char *ptr;
|
||||
int total_length;
|
||||
int len;
|
||||
int op;
|
||||
PROXYSOCKADDRTYPE saremote;
|
||||
struct pollfd fds[1];
|
||||
char vector[AUTH_VECTOR_LEN];
|
||||
radius_packet_t packet, rpacket;
|
||||
SASIZETYPE salen;
|
||||
int data_len;
|
||||
uint8_t *vendor_len;
|
||||
int count=0;
|
||||
uint8_t *attr;
|
||||
long vendor=0;
|
||||
@ -613,7 +600,6 @@ int radsend(struct clientparam * param, int auth, int stop){
|
||||
|
||||
attr = rpacket.data;
|
||||
count = total_length - 20;
|
||||
vendor_len = 0;
|
||||
|
||||
while (count >= 2) {
|
||||
if (!vendor && attr[0] == 0) {
|
||||
|
||||
@ -21,16 +21,17 @@ void * autochild(struct clientparam* param) {
|
||||
if (len != 1){
|
||||
param->res = 801;
|
||||
dolog(param, (unsigned char *)"");
|
||||
return 0;
|
||||
}
|
||||
if(*param->clibuf == 4 || *param->clibuf == 5) {
|
||||
param->service = S_SOCKS;
|
||||
return sockschild(param);
|
||||
return (void *)sockschild;
|
||||
}
|
||||
if(*param->clibuf == 22) {
|
||||
param->service = S_TLSPR;
|
||||
return tlsprchild(param);
|
||||
return (void *)tlsprchild;
|
||||
}
|
||||
param->service = S_PROXY;
|
||||
return proxychild(param);
|
||||
return (void *)proxychild;
|
||||
}
|
||||
|
||||
|
||||
16
src/common.c
16
src/common.c
@ -190,7 +190,7 @@ struct extparam conf = {
|
||||
.paused = 0,
|
||||
.archiverc = 0,
|
||||
.demon = 0,
|
||||
.maxchild = 500,
|
||||
.maxchild = DEFAULT_MAXCHILD,
|
||||
.backlog = 0,
|
||||
.needreload = 0,
|
||||
.timetoexit = 0,
|
||||
@ -681,20 +681,6 @@ int doconnect(struct clientparam * param){
|
||||
setopts(param->remsock, param->srv->srvsockopts);
|
||||
|
||||
param->srv->so._setsockopt(param->sostate, param->remsock, SOL_SOCKET, SO_LINGER, (char *)&lg, sizeof(lg));
|
||||
#ifdef REUSE
|
||||
{
|
||||
int opt;
|
||||
|
||||
#ifdef SO_REUSEADDR
|
||||
opt = 1;
|
||||
param->srv->so._setsockopt(param->sostate, param->remsock, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(int));
|
||||
#endif
|
||||
#ifdef SO_REUSEPORT
|
||||
opt = 1;
|
||||
param->srv->so._setsockopt(param->sostate, param->remsock, SOL_SOCKET, SO_REUSEPORT, (unsigned char *)&opt, sizeof(int));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#if defined SO_BINDTODEVICE
|
||||
if(param->srv->obindtodevice) {
|
||||
if(param->srv->so._setsockopt(param->sostate, param->remsock, SOL_SOCKET, SO_BINDTODEVICE, param->srv->obindtodevice, strlen(param->srv->obindtodevice) + 1))
|
||||
|
||||
@ -296,6 +296,7 @@ static int h_external(int argc, unsigned char ** argv){
|
||||
else conf.extsa6 = sa6;
|
||||
#else
|
||||
res = getip46(46, argv[1], (struct sockaddr *)&conf.extsa);
|
||||
if(!res) return 1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@ -517,7 +518,6 @@ static int h_auth(int argc, unsigned char **argv){
|
||||
}
|
||||
|
||||
static int h_users(int argc, unsigned char **argv){
|
||||
static char dummy;
|
||||
int j;
|
||||
unsigned char *arg;
|
||||
char *pw[2];
|
||||
@ -2025,7 +2025,7 @@ void freeconf(struct extparam *confp){
|
||||
#endif
|
||||
*SAFAMILY(&confp->intsa) = AF_INET;
|
||||
*SAFAMILY(&confp->extsa) = AF_INET;
|
||||
confp->maxchild = 100;
|
||||
confp->maxchild = DEFAULT_MAXCHILD;
|
||||
confp->backlog = 0;
|
||||
resolvfunc = NULL;
|
||||
numservers = 0;
|
||||
|
||||
@ -61,13 +61,6 @@ static void pr_ip(struct node *node, CBFUNC cbf, void*cb){
|
||||
if(node->value)(*cbf)(cb, buf, myinet_ntop(AF_INET, node -> value, buf, 4));
|
||||
}
|
||||
|
||||
#ifndef NOIPV6
|
||||
static void pr_ip6(struct node *node, CBFUNC cbf, void*cb){
|
||||
char buf[64];
|
||||
if(node->value)(*cbf)(cb, buf, myinet_ntop(AF_INET6, node -> value, buf, 16));
|
||||
}
|
||||
#endif
|
||||
|
||||
static void pr_sa(struct node *node, CBFUNC cbf, void*cb){
|
||||
#ifdef NOIPV6
|
||||
if(node->value)pr_ip(node, cbf, cb);
|
||||
|
||||
@ -35,7 +35,6 @@ void * dnsprchild(struct clientparam* param) {
|
||||
|
||||
|
||||
if(!(bbuf = malloc(BUFSIZE+2))){
|
||||
param->srv->fds.events = POLLIN;
|
||||
RETURN (21);
|
||||
}
|
||||
buf = bbuf+2;
|
||||
@ -59,7 +58,6 @@ void * dnsprchild(struct clientparam* param) {
|
||||
#else
|
||||
param->clisock = param->srv->srvsock;
|
||||
#endif
|
||||
param->srv->fds.events = POLLIN;
|
||||
|
||||
if(i < 0) {
|
||||
RETURN(813);
|
||||
@ -222,7 +220,6 @@ CLEANRET:
|
||||
#ifndef _WIN32
|
||||
param->clisock = INVALID_SOCKET;
|
||||
#endif
|
||||
freeparam(param);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
@ -325,7 +325,6 @@ CLEANRET:
|
||||
}
|
||||
if(req) free(req);
|
||||
if(buf) free(buf);
|
||||
freeparam(param);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
@ -36,7 +36,6 @@ void destroyhashtable(struct hashtable *ht){
|
||||
|
||||
int inithashtable(struct hashtable *ht, unsigned tablesize, unsigned poolsize, unsigned growlimit){
|
||||
unsigned i;
|
||||
clock_t c;
|
||||
|
||||
#ifdef _WIN32
|
||||
struct timeb tb;
|
||||
@ -48,7 +47,6 @@ int inithashtable(struct hashtable *ht, unsigned tablesize, unsigned poolsize, u
|
||||
struct timezone tz;
|
||||
gettimeofday(&tb, &tz);
|
||||
#endif
|
||||
c = clock();
|
||||
|
||||
if(tablesize < 2 || poolsize < tablesize || growlimit < poolsize) return 1;
|
||||
if(ht->ihashtable){
|
||||
@ -169,7 +167,6 @@ static void hashgrow(struct hashtable *ht){
|
||||
void hashadd(struct hashtable *ht, void* name, void* value, time_t expires){
|
||||
uint32_t hen, he;
|
||||
uint32_t *hep;
|
||||
int overwrite = 0;
|
||||
uint8_t hash[MAX_HASH_SIZE];
|
||||
uint32_t index;
|
||||
uint32_t last = 0;
|
||||
|
||||
@ -28,7 +28,7 @@ static void param2hash_add(const struct hashtable *ht, void *index, uint8_t *has
|
||||
void param2hash_search(const struct hashtable *ht, void *index, uint8_t *hash){
|
||||
struct clientparam *param = (struct clientparam *)index;
|
||||
unsigned type = param->srv->authcachetype;
|
||||
int len = 0, oplen = 0, acllen = 0, ulen = 0, plen = 0, hlen = 0, a1len = 0, a2len = 0, a3len = 0, p1len=0, p2len = 0;
|
||||
int oplen = 0, acllen = 0, ulen = 0, plen = 0, hlen = 0, a1len = 0, a2len = 0, a3len = 0, p1len=0, p2len = 0;
|
||||
|
||||
|
||||
if((type & 2) && param->username) ulen = strlen((const char *)param->username) + 1;
|
||||
@ -76,19 +76,6 @@ void param2hash_search(const struct hashtable *ht, void *index, uint8_t *hash){
|
||||
memcpy(param->hash, hash, ht->hash_size);
|
||||
}
|
||||
|
||||
static void udpparam2hash(const struct hashtable *ht, void *index, uint8_t *hash){
|
||||
struct clientparam *param = (struct clientparam *)index;
|
||||
mdh_ctx *bctx = mdh_init(MDH_BLAKE2, ht->hash_size);
|
||||
unsigned int blen = ht->hash_size;
|
||||
if(!bctx) return;
|
||||
mdh_update(bctx, SAADDR(¶m->srv->intsa), SAADDRLEN(¶m->srv->intsa));
|
||||
mdh_update(bctx, SAPORT(¶m->srv->intsa), 2);
|
||||
mdh_update(bctx, SAADDR(¶m->sincr), SAADDRLEN(¶m->sincr));
|
||||
mdh_update(bctx, SAPORT(¶m->sincr), 2);
|
||||
mdh_final(bctx, hash, &blen);
|
||||
mdh_free(bctx);
|
||||
}
|
||||
|
||||
struct hashtable dns_table = {char_index2hash, char_index2hash, 4, 32};
|
||||
struct hashtable dns6_table = {char_index2hash, char_index2hash, 16, 32};
|
||||
struct hashtable auth_table = {param2hash_add, param2hash_search, sizeof(struct authcache), 64};
|
||||
|
||||
@ -64,7 +64,7 @@ void * imappchild(struct clientparam* param) {
|
||||
if(socksend(param, param->clisock, buf, (int)strlen((char *)buf), conf.timeouts[STRING_S]) <= 0) {RETURN(698);}
|
||||
param->clientstarttls = S_IMAPP;
|
||||
if(!param->srv->targetport) param->srv->targetport = htons(143);
|
||||
return tlsprchild(param);
|
||||
return (void *)tlsprchild;
|
||||
}
|
||||
#endif
|
||||
if(!strncasecmp((char *)cmd, "LOGIN ", 6)){
|
||||
@ -238,7 +238,6 @@ CLEANRET:
|
||||
socksend(param, param->clisock, buf, (int)strlen((char *)buf),conf.timeouts[STRING_S]);
|
||||
}
|
||||
}
|
||||
freeparam(param);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
@ -338,7 +338,7 @@ void lognone(struct clientparam * param, const unsigned char *s) {
|
||||
clearstat(param);
|
||||
}
|
||||
|
||||
void logstdout(struct clientparam * param, const unsigned char *s) {
|
||||
NOINLINE void logstdout(struct clientparam * param, const unsigned char *s) {
|
||||
FILE *log;
|
||||
unsigned char tmpbuf[8192];
|
||||
|
||||
|
||||
@ -52,7 +52,6 @@ unsigned long preview = 0;
|
||||
char path[300];
|
||||
|
||||
static int counter = 0;
|
||||
static int timeo = 0;
|
||||
|
||||
static char * fp_stringtable[] = {
|
||||
/* 0 */ "HTTP/1.0 503 Service Unavailable\r\n"
|
||||
@ -261,10 +260,6 @@ static void removefps(struct fp_stream * fps){
|
||||
fps->state = 0;
|
||||
}
|
||||
|
||||
static int WINAPI fp_connect(SOCKET s, const struct sockaddr *name, fp_size_t namelen){
|
||||
return sso._connect(sso.state, s, name, namelen);
|
||||
}
|
||||
|
||||
void processcallbacks(struct fp_stream *fps, int what, char *msg, int size){
|
||||
struct fp_callback *cb;
|
||||
int state;
|
||||
|
||||
@ -90,10 +90,7 @@ static int pamfunc(struct clientparam *param)
|
||||
conv.appdata_ptr = (char *) param->password;
|
||||
|
||||
_3proxy_mutex_lock(&pam_mutex);
|
||||
if (!pamh)
|
||||
{
|
||||
retval = pam_start ((char *)service, (char *)param->username, &conv, &pamh);
|
||||
}
|
||||
if (retval == PAM_SUCCESS)
|
||||
retval = pam_set_item (pamh, PAM_USER, param->username);
|
||||
/*fprintf(stderr,"pam_set_item1 rc=%d\n",retval);*/
|
||||
|
||||
@ -34,13 +34,12 @@ static void* transparent_filter_open(void * idata, struct srvparam * param){
|
||||
|
||||
static FILTER_ACTION transparent_filter_client(void *fo, struct clientparam * param, void** fc){
|
||||
|
||||
socklen_t len;
|
||||
char addrbuf[64];
|
||||
int i=0;
|
||||
|
||||
len = sizeof(param->req);
|
||||
|
||||
#ifdef WITH_NETFILTER
|
||||
socklen_t len;
|
||||
|
||||
len = sizeof(param->req);
|
||||
#ifdef SO_ORIGINAL_DST
|
||||
|
||||
if(getsockopt(param->clisock,
|
||||
|
||||
@ -38,7 +38,7 @@ void * pop3pchild(struct clientparam* param) {
|
||||
if(socksend(param, param->clisock, (unsigned char *)"+OK Begin TLS negotiation\r\n", 27, conf.timeouts[STRING_S])!=27) {RETURN(623);}
|
||||
param->clientstarttls = S_POP3P;
|
||||
if(!param->srv->targetport) param->srv->targetport = htons(110);
|
||||
return tlsprchild(param);
|
||||
return (void *)tlsprchild;
|
||||
}
|
||||
#endif
|
||||
socksend(param, param->clisock, (unsigned char *)"-ERR need USER first\r\n", 22, conf.timeouts[STRING_S]);
|
||||
@ -74,7 +74,6 @@ CLEANRET:
|
||||
if(param->clisock != INVALID_SOCKET) {
|
||||
if ((param->res > 0 && param->res < 100) || (param->res > 611 && param->res <700)) socksend(param, param->clisock, (unsigned char *)"-ERR\r\n", 6,conf.timeouts[STRING_S]);
|
||||
}
|
||||
freeparam(param);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
13
src/proxy.c
13
src/proxy.c
@ -247,9 +247,13 @@ void * proxychild(struct clientparam* param) {
|
||||
int redirect = 0;
|
||||
int prefix = 0, ckeepalive=0;
|
||||
int ftp = 0;
|
||||
#ifndef ANONYMOUS
|
||||
int anonymous;
|
||||
#endif
|
||||
int sleeptime = 0;
|
||||
#ifndef WITHMAIN
|
||||
int reqsize, reqbufsize;
|
||||
#endif
|
||||
int authenticate;
|
||||
struct pollfd fds[2];
|
||||
SOCKET ftps;
|
||||
@ -265,7 +269,9 @@ void * proxychild(struct clientparam* param) {
|
||||
if(param->remsock != INVALID_SOCKET) haveconnection = 1;
|
||||
if(!(buf = malloc(BUFSIZE))) {RETURN(21);}
|
||||
bufsize = BUFSIZE;
|
||||
#ifndef ANONYMOUS
|
||||
anonymous = param->srv->anonymous;
|
||||
#endif
|
||||
for(;;){
|
||||
memset(buf, 0, bufsize);
|
||||
inbuf = 0;
|
||||
@ -548,8 +554,10 @@ for(;;){
|
||||
|
||||
buf[inbuf] = 0;
|
||||
|
||||
#ifndef WITHMAIN
|
||||
reqsize = (int)strlen((char *)req);
|
||||
reqbufsize = reqsize + 1;
|
||||
#endif
|
||||
|
||||
|
||||
if(param->srv->needuser > 1 && !param->username) {RETURN(4);}
|
||||
@ -701,7 +709,6 @@ for(;;){
|
||||
int sizetoken =-1;
|
||||
int modetoken =-1;
|
||||
int datetoken =-1;
|
||||
int spaces = 1;
|
||||
unsigned char * tokens[10];
|
||||
unsigned wordlen [10];
|
||||
unsigned char j=0;
|
||||
@ -734,7 +741,6 @@ for(;;){
|
||||
wordlen[datetoken] = ((unsigned)(tokens[1] - tokens[0])) + wordlen[1];
|
||||
sizetoken = 2;
|
||||
filetoken = 3;
|
||||
spaces = 10;
|
||||
}
|
||||
else {
|
||||
if(j < 8 || wordlen[0]!=10) continue;
|
||||
@ -864,7 +870,7 @@ for(;;){
|
||||
if(isconnect && param->redirtype != R_HTTP) {
|
||||
if(param->redirectfunc) {
|
||||
freeptr(&req); freeptr(&buf); freeptr(&ftpbase);
|
||||
return (*param->redirectfunc)(param);
|
||||
return (void *)param->redirectfunc;
|
||||
}
|
||||
param->res = mapsocket(param, conf.timeouts[CONNECTION_L]);
|
||||
RETURN(param->res);
|
||||
@ -1226,7 +1232,6 @@ CLEANRET:
|
||||
}
|
||||
logurl(param, (char *)buf, (char *)req, ftp);
|
||||
freeptr(&req); freeptr(&buf); freeptr(&ftpbase);
|
||||
freeparam(param);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
23
src/proxy.h
23
src/proxy.h
@ -34,6 +34,7 @@
|
||||
#define MAXUSERNAME 128
|
||||
#define _PASSWORD_LEN 256
|
||||
#define MAXNSERVERS 5
|
||||
#define DEFAULT_MAXCHILD 500
|
||||
|
||||
#define TCPBUFSIZE 65536
|
||||
#define SRVBUFSIZE (param->srv->bufsize?param->srv->bufsize:((param->service == S_UDPPM)?UDPBUFSIZE:TCPBUFSIZE))
|
||||
@ -103,7 +104,6 @@
|
||||
#include <pthread.h>
|
||||
#ifndef PTHREAD_STACK_MIN
|
||||
#define PTHREAD_STACK_MIN 32768
|
||||
#define sockerror strerror
|
||||
#endif
|
||||
void daemonize(void);
|
||||
#define SLEEPTIME 1000
|
||||
@ -112,6 +112,18 @@ void daemonize(void);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Keeps a callee with a large frame out of the caller's frame, e.g. the
|
||||
8K log buffer of logstdout() out of dolog(), which calls it in a branch
|
||||
taken only when there is no service.
|
||||
*/
|
||||
#if defined(__GNUC__)
|
||||
#define NOINLINE __attribute__((noinline))
|
||||
#elif defined(_MSC_VER)
|
||||
#define NOINLINE __declspec(noinline)
|
||||
#else
|
||||
#define NOINLINE
|
||||
#endif
|
||||
|
||||
/* Thread stack size, stacksize command value is added to it. BSD libc uses
|
||||
significantly more stack, e.g. in vfprintf() called by syslog().
|
||||
*/
|
||||
@ -213,7 +225,7 @@ void dolog(struct clientparam * param, const unsigned char *s);
|
||||
int dobuf(struct clientparam * param, unsigned char * buf, const unsigned char *s, const unsigned char * doublec);
|
||||
int dobuf2(struct clientparam * param, unsigned char * buf, const unsigned char *s, const unsigned char * doublec, struct tm* tm, char * format);
|
||||
extern FILE * stdlog;
|
||||
void logstdout(struct clientparam * param, const unsigned char *s);
|
||||
NOINLINE void logstdout(struct clientparam * param, const unsigned char *s);
|
||||
void logsyslog(struct clientparam * param, const unsigned char *s);
|
||||
void lognone(struct clientparam * param, const unsigned char *s);
|
||||
void logradius(struct clientparam * param, const unsigned char *s);
|
||||
@ -357,6 +369,13 @@ void * udppmchild(struct clientparam * param);
|
||||
void * adminchild(struct clientparam * param);
|
||||
void * ftpprchild(struct clientparam * param);
|
||||
void * tlsprchild(struct clientparam * param);
|
||||
/* Child functions return the child to redirect the request to, or NULL if
|
||||
the request is complete. childfunc() calls them and releases param.
|
||||
Recursive redirection, e.g. a socks service redirected to socks5, used to
|
||||
be limited by the stack size only, MAXCHILDREDIRECTS limits it now.
|
||||
*/
|
||||
#define MAXCHILDREDIRECTS 16
|
||||
void * childfunc(struct clientparam * param);
|
||||
|
||||
|
||||
struct datatype;
|
||||
|
||||
@ -13,13 +13,19 @@
|
||||
|
||||
/* Child functions do not call each other, a child requesting redirection to
|
||||
another child returns it instead of calling it, to keep the stack flat.
|
||||
NULL is returned by the child which completed the request, it has already
|
||||
released param and it must not be accessed after the call.
|
||||
The child which completed the request returns NULL. param is logged by
|
||||
the child and released here.
|
||||
*/
|
||||
void * childfunc(struct clientparam * param){
|
||||
PROXYFUNC pf = param->srv->pf;
|
||||
int i;
|
||||
|
||||
while(pf) pf = (PROXYFUNC)(*pf)(param);
|
||||
for(i = 0; pf && i < MAXCHILDREDIRECTS; i++) pf = (PROXYFUNC)(*pf)(param);
|
||||
if(pf){
|
||||
param->res = 101;
|
||||
dolog(param, (unsigned char *)"Redirection loop");
|
||||
}
|
||||
freeparam(param);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -133,7 +139,7 @@ void * threadfunc (void *p) {
|
||||
}
|
||||
}
|
||||
}
|
||||
((struct clientparam *) p)->srv->pf((struct clientparam *)p);
|
||||
childfunc((struct clientparam *)p);
|
||||
}
|
||||
#ifdef _WIN32
|
||||
return 0;
|
||||
@ -143,6 +149,20 @@ void * threadfunc (void *p) {
|
||||
}
|
||||
#undef param
|
||||
|
||||
#ifdef _WIN32
|
||||
/* Present since Windows 7 (SO_PORT_SCALABILITY) and Windows 10 / Server 2019
|
||||
(SO_REUSE_UNICASTPORT), define them if the SDK is older so the options can
|
||||
still be requested. setsockopt() just fails on a system which does not
|
||||
support them and the failure is ignored.
|
||||
*/
|
||||
#ifndef SO_PORT_SCALABILITY
|
||||
#define SO_PORT_SCALABILITY 0x3006
|
||||
#endif
|
||||
#ifndef SO_REUSE_UNICASTPORT
|
||||
#define SO_REUSE_UNICASTPORT 0x3007
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct socketoptions sockopts[] = {
|
||||
#ifdef TCP_NODELAY
|
||||
{TCP_NODELAY, "TCP_NODELAY"},
|
||||
@ -159,15 +179,15 @@ struct socketoptions sockopts[] = {
|
||||
#ifdef TCP_TIMESTAMPS
|
||||
{TCP_TIMESTAMPS, "TCP_TIMESTAMPS"},
|
||||
#endif
|
||||
#ifdef USE_TCP_FASTOPEN
|
||||
{USE_TCP_FASTOPEN, "USE_TCP_FASTOPEN"},
|
||||
#endif
|
||||
#ifdef SO_REUSEADDR
|
||||
{SO_REUSEADDR, "SO_REUSEADDR"},
|
||||
#endif
|
||||
#ifdef SO_REUSEPORT
|
||||
{SO_REUSEPORT, "SO_REUSEPORT"},
|
||||
#endif
|
||||
#ifdef SO_EXCLUSIVEADDRUSE
|
||||
{SO_EXCLUSIVEADDRUSE, "SO_EXCLUSIVEADDRUSE"},
|
||||
#endif
|
||||
#ifdef SO_PORT_SCALABILITY
|
||||
{SO_PORT_SCALABILITY, "SO_PORT_SCALABILITY"},
|
||||
#endif
|
||||
@ -291,6 +311,7 @@ int MODULEMAINFUNC (int argc, char** argv){
|
||||
#ifdef __linux__
|
||||
int saved_nsfd = -1;
|
||||
#endif
|
||||
#if !defined(PORTMAP) || !defined(NOPORTMAP)
|
||||
char loghelp[] =
|
||||
#ifdef STDMAIN
|
||||
#ifndef _WIN32
|
||||
@ -306,8 +327,8 @@ int MODULEMAINFUNC (int argc, char** argv){
|
||||
" -Di(DEVICENAME) bind internal interface to device, e.g. eth1\n"
|
||||
" -De(DEVICENAME) bind external interface to device, e.g. eth1\n"
|
||||
#endif
|
||||
#ifdef WITHSLICE
|
||||
" -s Use slice() - faster proxing, but no filtering for data\n"
|
||||
#ifdef WITHSPLICE
|
||||
" -s Use splice() - no filtering for data, off by default\n"
|
||||
#endif
|
||||
"-g(GRACE_TRAFF,GRACE_NUM,GRACE_DELAY) - delay GRACE_DELAY milliseconds before polling if average polling size below GRACE_TRAFF bytes and GRACE_NUM read operations in single directions are detected within 1 second to minimize polling\n"
|
||||
" -fFORMAT logging format (see documentation)\n"
|
||||
@ -329,6 +350,7 @@ int MODULEMAINFUNC (int argc, char** argv){
|
||||
" to-client (oc), to-server (os), listening (ol) socket, connect back client\n"
|
||||
" (or) socket, connect back server (oR) listening socket\n"
|
||||
" where possible options are: ";
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
unsigned long ul = 1;
|
||||
@ -581,7 +603,7 @@ int MODULEMAINFUNC (int argc, char** argv){
|
||||
srv.s_option = 1 + atoi(argv[i]+2);
|
||||
#ifdef WITHSPLICE
|
||||
else
|
||||
if(*(argv[i]+2)) srv.usesplice = atoi(argv[i]+2);
|
||||
srv.usesplice = *(argv[i]+2)? atoi(argv[i]+2) : 1;
|
||||
#endif
|
||||
break;
|
||||
case 'o':
|
||||
@ -701,7 +723,7 @@ int MODULEMAINFUNC (int argc, char** argv){
|
||||
return 2;
|
||||
};
|
||||
*newparam = defparam;
|
||||
return((*srv.pf)((void *)newparam)? 1:0);
|
||||
return(childfunc(newparam)? 1:0);
|
||||
|
||||
}
|
||||
#endif
|
||||
@ -789,8 +811,15 @@ int MODULEMAINFUNC (int argc, char** argv){
|
||||
if(*SAFAMILY(&srv.intsa) != AF_UNIX)
|
||||
#endif
|
||||
{
|
||||
/* SO_REUSEADDR is not set on Windows: it is not needed to rebind a listening
|
||||
port there, and it only allows another local process to bind the same
|
||||
address and port, with undefined behaviour as to which socket receives the
|
||||
connections. Use -olSO_EXCLUSIVEADDRUSE to prevent that instead.
|
||||
*/
|
||||
#ifndef _WIN32
|
||||
opt = 1;
|
||||
if(srv.so._setsockopt(srv.so.state, sock, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(int)))perror("setsockopt()");
|
||||
#endif
|
||||
#ifdef SO_REUSEPORT
|
||||
opt = 1;
|
||||
srv.so._setsockopt(srv.so.state, sock, SOL_SOCKET, SO_REUSEPORT, (char *)&opt, sizeof(int));
|
||||
@ -906,8 +935,10 @@ int MODULEMAINFUNC (int argc, char** argv){
|
||||
freesrvstrings(&srv, cbc_string, cbl_string);
|
||||
return -6;
|
||||
}
|
||||
#ifndef _WIN32
|
||||
opt = 1;
|
||||
srv.so._setsockopt(srv.so.state, srv.cbsock, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(int));
|
||||
#endif
|
||||
#ifdef SO_REUSEPORT
|
||||
opt = 1;
|
||||
srv.so._setsockopt(srv.so.state, srv.cbsock, SOL_SOCKET, SO_REUSEPORT, (char *)&opt, sizeof(int));
|
||||
@ -951,13 +982,7 @@ int MODULEMAINFUNC (int argc, char** argv){
|
||||
}
|
||||
if (iscbc) break;
|
||||
if (conf.paused != srv.paused) break;
|
||||
if (srv.fds.events & POLLIN) {
|
||||
error = srv.so._poll(srv.so.state, &srv.fds, 1, 1000);
|
||||
}
|
||||
else {
|
||||
usleep(SLEEPTIME);
|
||||
continue;
|
||||
}
|
||||
if (error >= 1) break;
|
||||
if (error == 0) continue;
|
||||
if (errno != EAGAIN && errno != EINTR) {
|
||||
@ -1220,7 +1245,7 @@ void srvinit(struct srvparam * srv, struct clientparam *param){
|
||||
srv->saved_nsfd = srv->i_nsfd = srv->o_nsfd = -1;
|
||||
#endif
|
||||
#ifdef WITHSPLICE
|
||||
srv->usesplice = 1;
|
||||
srv->usesplice = 0;
|
||||
#endif
|
||||
memset(param, 0, sizeof(struct clientparam));
|
||||
param->srv = srv;
|
||||
|
||||
13
src/smtpp.c
13
src/smtpp.c
@ -56,7 +56,10 @@ int readreply (struct clientparam* param) {
|
||||
|
||||
int readcommand (struct clientparam* param) {
|
||||
unsigned char * buf;
|
||||
int res, i, bufsize = 320;
|
||||
int i, bufsize = 320;
|
||||
#ifndef WITHMAIN
|
||||
int res;
|
||||
#endif
|
||||
int ret = 1;
|
||||
|
||||
if(!(buf = malloc(bufsize))) return 0;
|
||||
@ -82,7 +85,10 @@ int readcommand (struct clientparam* param) {
|
||||
|
||||
int readdata (struct clientparam* param) {
|
||||
unsigned char * buf;
|
||||
int res, i, bufsize = 4096;
|
||||
int i, bufsize = 4096;
|
||||
#ifndef WITHMAIN
|
||||
int res;
|
||||
#endif
|
||||
|
||||
if(!(buf = malloc(bufsize))) return 0;
|
||||
while ((i = sockgetlinebuf(param, CLIENT, buf, bufsize-1, '\n', conf.timeouts[STRING_L])) > 0 && !(i==3 && buf[0] == '.')){
|
||||
@ -132,7 +138,7 @@ void * smtppchild(struct clientparam* param) {
|
||||
if(socksend(param, param->clisock, (unsigned char *)"220 2.0.0 Ready to start TLS\r\n", 30, conf.timeouts[STRING_S])!=30) {RETURN(673);}
|
||||
param->clientstarttls = S_SMTPP;
|
||||
if(!param->srv->targetport) param->srv->targetport = htons(587);
|
||||
return tlsprchild(param);
|
||||
return (void *)tlsprchild;
|
||||
}
|
||||
#endif
|
||||
else if(!param->hostname) socksend(param, param->clisock, (unsigned char *)"571 need AUTH first\r\n", 22, conf.timeouts[STRING_S]);
|
||||
@ -319,7 +325,6 @@ CLEANRET:
|
||||
if ((param->res > 0 && param->res < 100) || (param->res > 661 && param->res <700)) socksend(param, param->clisock, (unsigned char *)"571 \r\n", 6,conf.timeouts[STRING_S]);
|
||||
}
|
||||
if(command) free(command);
|
||||
freeparam(param);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
#if WITHLOG > 1
|
||||
char logbuf[1024];
|
||||
#endif
|
||||
#define log(X) dolog(param,X)
|
||||
#define log(X) dolog(param,(const unsigned char *)(X))
|
||||
#else
|
||||
#define log(X)
|
||||
#endif
|
||||
@ -47,13 +47,15 @@ ssize_t splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t le
|
||||
int sockmap(struct clientparam * param, int timeo, int usesplice){
|
||||
uint64_t fromclient=0x7fffffffffffffff, fromserver =0x7fffffffffffffff;
|
||||
uint64_t inclientbuf = 0, inserverbuf = 0;
|
||||
int FROMCLIENT = 1, TOCLIENTBUF = 1, FROMCLIENTBUF = 1, TOSERVER = 1,
|
||||
FROMSERVER = 1, TOSERVERBUF = 1, FROMSERVERBUF = 1, TOCLIENT = 1;
|
||||
int FROMCLIENT = 1, TOCLIENTBUF = 1, TOSERVER = 1,
|
||||
FROMSERVER = 1, TOSERVERBUF = 1, TOCLIENT = 1;
|
||||
#if WITHLOG > 1
|
||||
int FROMCLIENTBUF = 1, FROMSERVERBUF = 1;
|
||||
#endif
|
||||
int HASERROR=0;
|
||||
int CLIENTTERMREAD = 0, CLIENTTERMWRITE = 0, SERVERTERMREAD = 0, SERVERTERMWRITE = 0;
|
||||
int after = 0;
|
||||
struct pollfd fds[8];
|
||||
struct pollfd *fdsp = fds;
|
||||
int fdsc = 0;
|
||||
int sleeptime = 0;
|
||||
FILTER_ACTION action;
|
||||
|
||||
19
src/socks.c
19
src/socks.c
@ -53,7 +53,6 @@ void * sockschild(struct clientparam* param) {
|
||||
int ver=0;
|
||||
int havepass = 0;
|
||||
PROXYSOCKADDRTYPE sin;
|
||||
int len;
|
||||
|
||||
|
||||
param->service = S_SOCKS;
|
||||
@ -212,19 +211,7 @@ void * sockschild(struct clientparam* param) {
|
||||
param->operation = command == 2?BIND:UDPASSOC;
|
||||
if(command == 2){
|
||||
if ((param->remsock=param->srv->so._socket(param->sostate, SASOCK(¶m->req), SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {RETURN (11);}
|
||||
#ifdef REUSE
|
||||
{
|
||||
int opt;
|
||||
#ifdef SO_REUSEADDR
|
||||
opt = 1;
|
||||
param->srv->so._setsockopt(param->sostate, param->remsock, SOL_SOCKET, SO_REUSEADDR, (unsigned char *)&opt, sizeof(int));
|
||||
#endif
|
||||
#ifdef SO_REUSEPORT
|
||||
opt = 1;
|
||||
param->srv->so._setsockopt(param->sostate, param->remsock, SOL_SOCKET, SO_REUSEPORT, (unsigned char *)&opt, sizeof(int));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
setopts(param->remsock, param->srv->lissockopts);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -385,9 +372,8 @@ fflush(stderr);
|
||||
switch(command) {
|
||||
case 1:
|
||||
if(param->redirectfunc){
|
||||
void *ret = (*param->redirectfunc)(param);
|
||||
if(buf)free(buf);
|
||||
return ret;
|
||||
return (void *)param->redirectfunc;
|
||||
}
|
||||
param->res = mapsocket(param, conf.timeouts[CONNECTION_L]);
|
||||
break;
|
||||
@ -467,7 +453,6 @@ fflush(stderr);
|
||||
dolog(param, buf);
|
||||
free(buf);
|
||||
}
|
||||
freeparam(param);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
@ -53,7 +53,6 @@ static char *client_ca_store = NULL;
|
||||
static int mitm = 0;
|
||||
static int serv = 0;
|
||||
static int cli = 0;
|
||||
static int ssl_inited = 0;
|
||||
static int client_min_proto_version = 0;
|
||||
static int client_max_proto_version = 0;
|
||||
static int server_min_proto_version = 0;
|
||||
@ -486,10 +485,6 @@ EVP_PKEY * getKey(const char *fname){
|
||||
return key;
|
||||
}
|
||||
|
||||
static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx){
|
||||
return preverify_ok;
|
||||
}
|
||||
|
||||
#ifdef WITH_WOLFSSL
|
||||
/* wolfSSL's SSL_CTX_use_PrivateKey(EVP_PKEY*) compat is unreliable: it
|
||||
* silently fails (returns 0, no error queued) for keys loaded via
|
||||
|
||||
86
src/ssllib.c
86
src/ssllib.c
@ -72,6 +72,18 @@ static size_t bin2hex (const unsigned char* bin, size_t bin_length, char* str, s
|
||||
return p - str;
|
||||
}
|
||||
|
||||
static int copy_ext(X509 *dst_cert, X509 *src_cert, int nid)
|
||||
{
|
||||
X509_EXTENSION *ext;
|
||||
int idx;
|
||||
|
||||
idx = X509_get_ext_by_NID(src_cert, nid, -1);
|
||||
if(idx < 0) return 0;
|
||||
if(!(ext = X509_get_ext(src_cert, idx))) return 0;
|
||||
return X509_add_ext(dst_cert, ext, -1) > 0;
|
||||
}
|
||||
|
||||
#ifndef WITH_WOLFSSL
|
||||
static int add_ext(X509 *cert, int nid, const char *value)
|
||||
{
|
||||
X509_EXTENSION *ex;
|
||||
@ -93,11 +105,11 @@ static int add_ext(X509 *cert, int nid, const char *value)
|
||||
X509_EXTENSION_free(ex);
|
||||
return err > 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
SSL_CERT ssl_copy_cert(SSL_CERT cert, SSL_CONFIG *config)
|
||||
{
|
||||
int err = -1;
|
||||
int san_idx;
|
||||
BIO *fcache;
|
||||
X509 *src_cert = (X509 *) cert;
|
||||
X509 *dst_cert = NULL;
|
||||
@ -153,7 +165,11 @@ SSL_CERT ssl_copy_cert(SSL_CERT cert, SSL_CONFIG *config)
|
||||
X509_free(dst_cert);
|
||||
return NULL;
|
||||
}
|
||||
#if !defined(WITH_WOLFSSL) && OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
/* wolfSSL has no X509_set1_notBefore/X509_set1_notAfter before 5.7.2,
|
||||
X509_set_notBefore/X509_set_notAfter are available in every version and
|
||||
copy the time the same way.
|
||||
*/
|
||||
#if defined(WITH_WOLFSSL) || OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
if(!X509_set_notBefore(dst_cert, X509_get_notBefore(src_cert))
|
||||
|| !X509_set_notAfter(dst_cert, X509_get_notAfter(src_cert))){
|
||||
#else
|
||||
@ -163,26 +179,30 @@ SSL_CERT ssl_copy_cert(SSL_CERT cert, SSL_CONFIG *config)
|
||||
X509_free(dst_cert);
|
||||
return NULL;
|
||||
}
|
||||
san_idx = X509_get_ext_by_NID(src_cert, NID_subject_alt_name, -1);
|
||||
if(san_idx >= 0){
|
||||
X509_EXTENSION *san;
|
||||
san = X509_get_ext(src_cert, san_idx);
|
||||
if(san && !X509_add_ext(dst_cert, san, -1)){
|
||||
X509_free(dst_cert);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
/* Extensions required from an end entity certificate. Without EKU
|
||||
* serverAuth Apple's TLS stack (and Chrome on macOS/iOS, which uses it)
|
||||
* rejects the certificate. keyUsage is intentionally not set: it depends
|
||||
* on the type of the key being reused for every generated certificate,
|
||||
* and an absent keyUsage places no restriction.
|
||||
/* Copy the extensions an end entity certificate is expected to have.
|
||||
* The extensions which break chain validation (AKI, CRL distribution
|
||||
* points, certificate policies, ...) are intentionally not copied.
|
||||
* A copy may fail: wolfSSL keeps extKeyUsage in its own form and can
|
||||
* not add back the one it returns, it is not fatal.
|
||||
*/
|
||||
if(!add_ext(dst_cert, NID_basic_constraints, "critical,CA:FALSE")
|
||||
|| !add_ext(dst_cert, NID_ext_key_usage, "serverAuth")){
|
||||
X509_free(dst_cert);
|
||||
return NULL;
|
||||
}
|
||||
copy_ext(dst_cert, src_cert, NID_subject_alt_name);
|
||||
#ifndef WITH_WOLFSSL
|
||||
/* Without EKU serverAuth Apple's TLS stack (and Chrome on macOS/iOS,
|
||||
* which uses it) rejects the certificate, generate the extensions the
|
||||
* server certificate has no usable ones to copy. keyUsage is not set:
|
||||
* it depends on the type of the key reused for every generated
|
||||
* certificate, and an absent keyUsage places no restriction.
|
||||
* wolfSSL_X509V3_EXT_conf_nid() is a stub returning NULL in every
|
||||
* wolfSSL version, the extensions can not be generated there.
|
||||
*/
|
||||
if(!copy_ext(dst_cert, src_cert, NID_basic_constraints))
|
||||
add_ext(dst_cert, NID_basic_constraints, "critical,CA:FALSE");
|
||||
if(!copy_ext(dst_cert, src_cert, NID_ext_key_usage))
|
||||
add_ext(dst_cert, NID_ext_key_usage, "serverAuth");
|
||||
#else
|
||||
copy_ext(dst_cert, src_cert, NID_basic_constraints);
|
||||
copy_ext(dst_cert, src_cert, NID_ext_key_usage);
|
||||
#endif
|
||||
err = X509_sign(dst_cert, config->CA_key, EVP_sha256());
|
||||
if(!err){
|
||||
X509_free(dst_cert);
|
||||
@ -256,10 +276,10 @@ void _ssl_cert_free(SSL_CERT cert)
|
||||
#define LEGACY_SSL_THREADING 0
|
||||
#endif
|
||||
|
||||
#if LEGACY_SSL_THREADING
|
||||
/* This array will store all of the mutexes available to OpenSSL. */
|
||||
static _3proxy_mutex_t *mutex_buf= NULL;
|
||||
|
||||
|
||||
static void locking_function(int mode, int n, const char * file, int line)
|
||||
{
|
||||
if (mode & CRYPTO_LOCK)
|
||||
@ -276,6 +296,7 @@ static unsigned long id_function(void)
|
||||
return ((unsigned long)pthread_self());
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
int thread_setup(void)
|
||||
{
|
||||
@ -289,29 +310,8 @@ int thread_setup(void)
|
||||
_3proxy_mutex_init(mutex_buf +i);
|
||||
CRYPTO_set_id_callback(id_function);
|
||||
CRYPTO_set_locking_callback(locking_function);
|
||||
return 1;
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
int thread_cleanup(void)
|
||||
{
|
||||
#if LEGACY_SSL_THREADING
|
||||
int i;
|
||||
|
||||
if (!mutex_buf)
|
||||
return 0;
|
||||
CRYPTO_set_id_callback(NULL);
|
||||
CRYPTO_set_locking_callback(NULL);
|
||||
for (i = 0; i < CRYPTO_num_locks( ); i++)
|
||||
_3proxy_mutex_destroy(mutex_buf +i);
|
||||
free(mutex_buf);
|
||||
mutex_buf = NULL;
|
||||
return 1;
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -182,7 +182,7 @@ int
|
||||
#ifdef WITH_UN
|
||||
#define PROXYSOCKADDRTYPE struct sockaddr_storage
|
||||
#else
|
||||
#ifndef NOIPv6
|
||||
#ifndef NOIPV6
|
||||
#define PROXYSOCKADDRTYPE struct sockaddr_in6
|
||||
#else
|
||||
#define PROXYSOCKADDRTYPE struct sockaddr_in
|
||||
@ -798,7 +798,7 @@ extern struct hashtable udp_table;
|
||||
|
||||
struct authcache {
|
||||
unsigned char username[64];
|
||||
#ifndef NOIPv6
|
||||
#ifndef NOIPV6
|
||||
uint8_t sincr_addr[16];
|
||||
uint8_t sinsl_addr[16];
|
||||
#else
|
||||
|
||||
@ -40,14 +40,13 @@ void * tcppmchild(struct clientparam* param) {
|
||||
if(action != PASS) RETURN(19);
|
||||
}
|
||||
if(param->redirectfunc){
|
||||
return (*param->redirectfunc)(param);
|
||||
return (void *)param->redirectfunc;
|
||||
}
|
||||
|
||||
RETURN (mapsocket(param, conf.timeouts[CONNECTION_L]));
|
||||
CLEANRET:
|
||||
|
||||
dolog(param, param->hostname);
|
||||
freeparam(param);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
17
src/tlspr.c
17
src/tlspr.c
@ -19,20 +19,6 @@ unsigned size16(unsigned char *buf){
|
||||
return res;
|
||||
}
|
||||
|
||||
int readtls(struct clientparam *param, int direction, unsigned char *buf, int bufsize){
|
||||
int res = 0;
|
||||
int len;
|
||||
|
||||
if(bufsize < 3) return -1;
|
||||
res = sockgetlinebuf(param, direction, buf, 3, EOF, conf.timeouts[STRING_S]);
|
||||
if(res !=3 || buf[0] != 22 || buf[1] != 3) return -2;
|
||||
len = size16(buf+3);
|
||||
if((len+3) > bufsize) return -3;
|
||||
res = sockgetlinebuf(param, direction, buf+3, len, EOF, conf.timeouts[STRING_S]);
|
||||
if(res != len) return -4;
|
||||
return len+3;
|
||||
}
|
||||
|
||||
#define BSIZE (4096)
|
||||
#define SNILEN (256)
|
||||
#define PROTOLEN (32)
|
||||
@ -396,7 +382,7 @@ void * tlsprchild(struct clientparam* param) {
|
||||
if(action != PASS) RETURN(19);
|
||||
}
|
||||
if(param->redirectfunc && param->redirectfunc != tlsprchild){
|
||||
return (*param->redirectfunc)(param);
|
||||
return (void *)param->redirectfunc;
|
||||
}
|
||||
|
||||
if(stlsproto){
|
||||
@ -471,7 +457,6 @@ CLEANRET:
|
||||
|
||||
sprintf(req, "%sv%d.%d %s %s", lv<0?"NONE":lv?"TLS":"SSL", lv<0?0:lv?1:3, lv<0?0:lv?lv-1:0, param->hostname?(char *)param->hostname:"-", proto);
|
||||
dolog(param, (unsigned char *)req);
|
||||
freeparam(param);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
@ -87,7 +87,6 @@ CLEANRET:
|
||||
_3proxy_sem_unlock(udpinit);
|
||||
dolog(param, NULL);
|
||||
param->clisock = INVALID_SOCKET;
|
||||
freeparam(param);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
@ -615,6 +615,5 @@ CLEANRET:
|
||||
if(buf) free(buf);
|
||||
dolog(param, (unsigned char *)req);
|
||||
if(req)free(req);
|
||||
freeparam(param);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user