Compare commits

...

6 Commits

Author SHA1 Message Date
Pаramtamtām
85323fa83b
Merge ccdecfd832 into 84879cc0ba 2026-06-03 10:50:48 +03:00
Vladimir Dubrovin
84879cc0ba Add public cert to build 2026-06-03 10:34:38 +03:00
Vladimir Dubrovin
757ad916ec Sign docker images
Some checks failed
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Has been cancelled
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Has been cancelled
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Has been cancelled
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Has been cancelled
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Has been cancelled
2026-06-02 18:12:48 +03:00
Vladimir Dubrovin
fbc3ed5a18 Update README.md 2026-06-02 16:36:38 +03:00
Vladimir Dubrovin
69862b67cb Check bandlims for UDP traffic 2026-06-02 14:23:52 +03:00
Vladimir Dubrovin
fd7b25bf06 Use non-blocking sockets for UDP 2026-06-02 13:43:56 +03:00
11 changed files with 113 additions and 26 deletions

View File

@ -47,6 +47,13 @@ jobs:
run: |
$pfx_cert_byte = [System.Convert]::FromBase64String("${{ secrets.WINDOWS_CERTIFICATE }}")
[System.IO.File]::WriteAllBytes("${{ github.workspace }}\cert.pfx", $pfx_cert_byte)
- name: Extract public certificate
shell: pwsh
env:
CERT_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
run: |
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2("${{ github.workspace }}\cert.pfx", "$env:CERT_PASSWORD")
[System.IO.File]::WriteAllBytes("${{ github.workspace }}\3proxy.crt", $cert.Export("Cert"))
- name: Sign
shell: pwsh
run: |
@ -83,6 +90,7 @@ jobs:
copy authors dist\3proxy\
copy README.md dist\3proxy\
copy rus.3ps dist\3proxy\
copy 3proxy.crt dist\3proxy\
- name: Get artifact
uses: actions/upload-artifact@v7
with:

View File

@ -48,6 +48,13 @@ jobs:
run: |
$pfx_cert_byte = [System.Convert]::FromBase64String("${{ secrets.WINDOWS_CERTIFICATE }}")
[System.IO.File]::WriteAllBytes("${{ github.workspace }}\cert.pfx", $pfx_cert_byte)
- name: Extract public certificate
shell: pwsh
env:
CERT_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
run: |
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2("${{ github.workspace }}\cert.pfx", "$env:CERT_PASSWORD")
[System.IO.File]::WriteAllBytes("${{ github.workspace }}\3proxy.crt", $cert.Export("Cert"))
- name: Sign
shell: pwsh
run: |
@ -84,6 +91,7 @@ jobs:
copy authors dist\3proxy\
copy README.md dist\3proxy\
copy rus.3ps dist\3proxy\
copy 3proxy.crt dist\3proxy\
- name: Get artifact
uses: actions/upload-artifact@v7
with:

View File

@ -47,6 +47,13 @@ jobs:
run: |
$pfx_cert_byte = [System.Convert]::FromBase64String("${{ secrets.WINDOWS_CERTIFICATE }}")
[System.IO.File]::WriteAllBytes("${{ github.workspace }}\cert.pfx", $pfx_cert_byte)
- name: Extract public certificate
shell: pwsh
env:
CERT_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
run: |
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2("${{ github.workspace }}\cert.pfx", "$env:CERT_PASSWORD")
[System.IO.File]::WriteAllBytes("${{ github.workspace }}\3proxy.crt", $cert.Export("Cert"))
- name: Sign
shell: pwsh
run: |
@ -83,6 +90,7 @@ jobs:
copy authors dist\3proxy\
copy README.md dist\3proxy\
copy rus.3ps dist\3proxy\
copy 3proxy.crt dist\3proxy\
- name: Get artifact
uses: actions/upload-artifact@v7
with:

View File

@ -8,6 +8,7 @@ on:
permissions:
contents: read
packages: write
id-token: write
env:
REGISTRY: ghcr.io
@ -46,6 +47,9 @@ jobs:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Install cosign
uses: sigstore/cosign-installer@v3
- name: Login to GHCR
if: github.event_name != 'pull_request'
uses: docker/login-action@v4
@ -81,3 +85,15 @@ jobs:
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.tags.outputs.full }}
- name: Sign images
if: github.event_name != 'pull_request'
env:
TAGS_MINIMAL: ${{ steps.tags.outputs.minimal }}
TAGS_BUSYBOX: ${{ steps.tags.outputs.busybox }}
TAGS_FULL: ${{ steps.tags.outputs.full }}
run: |
IFS=',' read -ra TAGS <<< "$TAGS_MINIMAL,$TAGS_BUSYBOX,$TAGS_FULL"
for tag in "${TAGS[@]}"; do
cosign sign --yes "$tag"
done

View File

@ -7,6 +7,7 @@ on:
permissions:
contents: read
id-token: write
env:
REGISTRY: docker.io
@ -44,6 +45,9 @@ jobs:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Install cosign
uses: sigstore/cosign-installer@v3
- name: Login to Docker Hub
if: github.event_name != 'pull_request'
uses: docker/login-action@v4
@ -77,3 +81,15 @@ jobs:
platforms: linux/amd64,linux/arm64,linux/arm/v7,ppc64le
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.tags.outputs.full }}
- name: Sign images
if: github.event_name != 'pull_request'
env:
TAGS_MINIMAL: ${{ steps.tags.outputs.minimal }}
TAGS_BUSYBOX: ${{ steps.tags.outputs.busybox }}
TAGS_FULL: ${{ steps.tags.outputs.full }}
run: |
IFS=',' read -ra TAGS <<< "$TAGS_MINIMAL,$TAGS_BUSYBOX,$TAGS_FULL"
for tag in "${TAGS[@]}"; do
cosign sign --yes "$tag"
done

View File

@ -36,26 +36,38 @@ Documentation (man pages and HTML) available with download, on https://3proxy.or
### Default image (`:latest`):
Full installation requires to mount /etc/3proxy directory with 3proxy.cfg files.
Full installation requires to mount /etc/3proxy/3proxy.cfg files.
to run:
For docker, config can be provided via `docker config`
```
echo "
log
echo "log
nserver 8.8.8.8
nscache 65536
proxy -p3129" | docker config create 3proxy
docker run --read-only -p 3129:3129 --config source=3proxy,target=/etc/3proxy/3proxy.cfg --name 3proxy.full docker.io/3proxy/3proxy
```
`podman` does not support `config` as above.
Mounts may be used as config alternative. `podman` used in example below can be replaced with `docker`:
```
echo "log
nserver 8.8.8.8
nscache 65536
proxy -p3129" >/path/to/local/config/directory/3proxy.cfg
podman run --read-only -p 3129:3129 -v /path/to/local/config/directory/3proxy.cfg:/etc/3proxy/3proxy.cfg --name 3proxy.full 3proxy.full
```
use `log` without pathname in config to log to stdout.
plugins are located in /usr/local/3proxy/libexec (/libexec for chroot config) and since 0.9.6 symlinked by /lib and /lib64 in both chroot and non-chroot configurations, so no full path is required in `plugin` command. Use e.g. `plugin SSLPlugin.ls.so ssl_plugin`. SSLPlugin is supported since 0.9.6. Some proxy types (e.g. SOCKSv5 UDPASSCOC, SOCKSv5 BIND functionality, ftp proxy) require access to ephemeral port, you may use e.g. -`-network host` mode or `-P` for `docker run`.
since 0.9.6 images are distroless (except :busybox) it's recommended to use with read only file system, there are no benefits from chroot. For compatibility, you still can use chroot installation by mounting directory with 3proxy.cfg to /usr/local/3proxy/config.
### Busybox image (`:busybox`):
Full with busybox added, to allow shell commands inside container. All libraries are in /lib, so chroot configuration can not use plugins.
`full` with busybox added, to allow `sh` and few more commands like `sed` inside container. All libraries are in /lib, so chroot configuration can not use plugins.
### Interactive `:minimal` image:

View File

@ -147,9 +147,9 @@ void * dnsprchild(struct clientparam* param) {
}
else {
#ifdef _WIN32
/* ioctlsocket(param->remsock, FIONBIO, &ul); */
ioctlsocket(param->remsock, FIONBIO, &ul);
#else
/* fcntl(param->remsock,F_SETFL,O_NONBLOCK); */
fcntl(param->remsock, F_SETFL, O_NONBLOCK | fcntl(param->remsock, F_GETFL));
#endif
}

View File

@ -1020,6 +1020,7 @@ int MODULEMAINFUNC (int argc, char** argv){
if(hashresolv(&udp_table, &defparam, &toparam, NULL)) {
int i, len=0;
if(!toparam->bandlimfunc || !(*toparam->bandlimfunc)(toparam, 0, srv.udplen)){
if(toparam->udp_nhops){
for(i=1; i < toparam->udp_nhops; i++){
len+=socks5_udp_build_hdr(srv.udpbuf2+len, &toparam->udp_relay[i-1]);
@ -1031,6 +1032,7 @@ int MODULEMAINFUNC (int argc, char** argv){
srv.so._sendto(toparam->sostate, toparam->remsock, (char *)srv.udpbuf2, len, 0, (struct sockaddr *)&toparam->sinsr, SASIZE(&toparam->sinsr));
toparam->statscli64 += srv.udplen;
toparam->nwrites++;
}
_3proxy_sem_unlock(udpinit);
continue;
}

View File

@ -255,6 +255,11 @@ void * sockschild(struct clientparam* param) {
if(switch_ns(param->srv, param->srv->o_nsfd)) {RETURN(11);}
#endif
if ((param->remsock=param->srv->so._socket(param->sostate, SASOCK(&param->req), SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {RETURN (11);}
#ifdef _WIN32
{ unsigned long ul = 1; ioctlsocket(param->remsock, FIONBIO, &ul); }
#else
fcntl(param->remsock, F_SETFL, O_NONBLOCK | fcntl(param->remsock, F_GETFL));
#endif
}
if(command > 1) {
@ -275,6 +280,11 @@ fflush(stderr);
#endif
param->clisock = param->srv->so._socket(param->sostate, SASOCK(&param->sincr), SOCK_DGRAM, IPPROTO_UDP);
if(param->clisock == INVALID_SOCKET) {RETURN(11);}
#ifdef _WIN32
{ unsigned long ul = 1; ioctlsocket(param->clisock, FIONBIO, &ul); }
#else
fcntl(param->clisock, F_SETFL, O_NONBLOCK | fcntl(param->clisock, F_GETFL));
#endif
sin = param->sincl;
*SAPORT(&sin) = 0;
if(param->srv->so._bind(param->sostate, param->clisock,(struct sockaddr *)&sin,SASIZE(&sin))) {RETURN (12);}

View File

@ -61,6 +61,7 @@ void * udppmchild(struct clientparam* param) {
if(!(param->srvbuf = malloc(UDPBUFSIZE)))RETURN(11);
param->srvbufsize = UDPBUFSIZE;
}
if(!param->bandlimfunc || !(*param->bandlimfunc)(param, 0, param->srv->udplen)){
if(param->udp_nhops){
for(i=1; i < param->udp_nhops; i++){
len+=socks5_udp_build_hdr(param->srvbuf+len, &param->udp_relay[i-1]);
@ -70,10 +71,11 @@ void * udppmchild(struct clientparam* param) {
memcpy(param->srvbuf+len, param->srv->udpbuf, param->srv->udplen > UDPBUFSIZE - len?UDPBUFSIZE - len : param->srv->udplen);
len += param->srv->udplen > UDPBUFSIZE - len?UDPBUFSIZE - len : param->srv->udplen;
param->srv->so._sendto(param->sostate, param->remsock, (char *)param->srvbuf, len, 0, (struct sockaddr *)&param->sinsr, SASIZE(&param->sinsr));
_3proxy_sem_unlock(udpinit);
param->statscli64 += param->srvinbuf;
param->srvinbuf = 0;
param->nwrites++;
}
_3proxy_sem_unlock(udpinit);
param->srvinbuf = 0;
param->clisock = param->srv->srvsock;
param->waitserver64 = 0x7fffffffffffffff;
param->res = udpsockmap(param, conf.timeouts[STRING_L]);

View File

@ -106,6 +106,7 @@ int udpsockmap(struct clientparam *param, int timeo)
len = param->srv->so._recvfrom(param->sostate, param->clisock,
(char *)param->srvbuf + recvoff, UDPBUFSIZE - recvoff,
0, (struct sockaddr *)&sin, &sasize);
if (len < 0 && (errno == EAGAIN || errno == EINTR)) continue;
if (len <= 0) return 482;
if (SAADDRLEN(&sin) != SAADDRLEN(&param->sincr) ||
@ -123,6 +124,8 @@ int udpsockmap(struct clientparam *param, int timeo)
continue;
}
if(param->bandlimfunc && (*param->bandlimfunc)(param, 0, len)) continue;
if (nhops == 0) {
int i;
if (len < 10 || param->srvbuf[0] || param->srvbuf[1] || param->srvbuf[2])
@ -182,6 +185,7 @@ int udpsockmap(struct clientparam *param, int timeo)
len = param->srv->so._recvfrom(param->sostate, param->remsock,
(char *)param->srvbuf + hdrsize, UDPBUFSIZE - hdrsize, 0,
(struct sockaddr *)&from, &sasize);
if (len < 0 && (errno == EAGAIN || errno == EINTR)) continue;
if (len <= 0) return 486;
if (nhops >= 1) {
if (!SAISNULL(&param->sinsr) && *SAPORT(&param->sinsr)) {
@ -193,6 +197,7 @@ int udpsockmap(struct clientparam *param, int timeo)
}
param->statssrv64 += len;
param->nreads++;
if(param->bandlimfunc && (*param->bandlimfunc)(param, len, 0)) continue;
sendlen = len;
if (nhops == 0) {
param->srvbuf[0] = param->srvbuf[1] = param->srvbuf[2] = 0;