diff --git a/Basis/Functions.py b/Basis/Functions.py index 31bb79e..744d1a3 100644 --- a/Basis/Functions.py +++ b/Basis/Functions.py @@ -2,8 +2,8 @@ # -*- coding: utf-8 -*- import time +import psutil import random -import socket from Basis.Logger import logging @@ -31,38 +31,35 @@ def getAvailablePort(rangeStart: int = 41952, rangeEnd: int = 65535) -> int: # def checkPortStatus(port: int) -> bool: # check if the port is occupied - ipv4Tcp = None - ipv4Udp = None - ipv6Tcp = None - ipv6Udp = None - try: - ipv4Tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - ipv4Udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - ipv4Tcp.bind(('0.0.0.0', port)) - ipv4Udp.bind(('0.0.0.0', port)) - ipv4Tcp.close() - ipv4Udp.close() - ipv6Tcp = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) - ipv6Udp = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) - ipv6Tcp.bind(('::', port)) - ipv6Udp.bind(('::', port)) - ipv6Tcp.close() - ipv6Udp.close() - logging.debug('check status of port %i -> available' % port) - return True # IPv4 TCP / IPv4 UDP / IPv6 TCP / IPv6 UDP are normal - except: - logging.debug('check status of port %i -> occupied' % port) - return False - finally: # close socket - try: - ipv4Tcp.close() - except: pass - try: - ipv4Udp.close() - except: pass - try: - ipv6Tcp.close() - except: pass - try: - ipv6Udp.close() - except: pass + logging.debug('check status of port %i -> available' % port) + for connection in networkStatus(): # scan every connections + if connection['local']['port'] == port: # port occupied (whatever ipv4-tcp / ipv4-udp / ipv6-tcp / ipv6-udp) + logging.debug('check status of port %i -> occupied' % port) + return False + return True + + +def networkStatus() -> list: # get all network connections + result = [] + for connection in psutil.net_connections(): + if not connection.family.name.startswith('AF_INET'): # AF_INET / AF_INET6 + continue + if connection.type.name not in ['SOCK_STREAM', 'SOCK_DGRAM']: # TCP / UDP + continue + result.append({ + 'fd': connection.fd, + 'family': 'ipv6' if connection.family.name[-1] == '6' else 'ipv4', # ip version + 'type': 'tcp' if connection.type.name == 'SOCK_STREAM' else 'udp', # tcp or udp + 'local': { # local bind address + 'addr': connection.laddr.ip, + 'port': connection.laddr.port, + }, + 'remote': { # remote address + 'addr': connection.raddr.ip, + 'port': connection.raddr.port, + } if len(connection.raddr) != 0 else None, + 'status': connection.status, + 'pid': connection.pid, # process id + }) + logging.debug('get network status -> found %i connections' % len(result)) + return result diff --git a/Dockerfile b/Dockerfile index 56832ec..af5be5e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -90,6 +90,20 @@ RUN \ mv ../bin/ss-bootstrap-* /tmp/ RUN strip /tmp/ss-bootstrap-* +# Combine shadowsocks dependencies +FROM python:3.10-alpine3.16 AS shadowsocks +COPY --from=ss-rust /tmp/ss-rust-* /release/ +COPY --from=ss-libev /tmp/ss-libev-* /release/ +COPY --from=ss-bootstrap /tmp/ss-bootstrap-* /release/ +RUN \ + PYTHON_PACKAGE="/usr/local/lib/$(ls /usr/local/lib/ | grep ^python)/site-packages" && \ + ln -s ${PYTHON_PACKAGE}/ssr-python/local.py /release/ssr-local && \ + ln -s ${PYTHON_PACKAGE}/ssr-python/server.py /release/ssr-server && \ + ln -s ${PYTHON_PACKAGE}/ss-python/local.py /release/ss-python-local && \ + ln -s ${PYTHON_PACKAGE}/ss-python/server.py /release/ss-python-server && \ + ln -s ${PYTHON_PACKAGE}/ss-python-legacy/local.py /release/ss-python-legacy-local && \ + ln -s ${PYTHON_PACKAGE}/ss-python-legacy/server.py /release/ss-python-legacy-server + # Compile openssl (old version, for shadowsocks method -> idea-cfb / seed-cfb) FROM alpine:3.16 AS openssl ENV OPENSSL_VER="1.0.2" @@ -103,32 +117,16 @@ RUN \ mv ./libcrypto.so.1.0.0 /tmp/ RUN strip /tmp/libcrypto.so.1.0.0 -# Build numpy and salsa20 python module -FROM python:3.10-alpine3.16 AS salsa20 +# Build python module (numpy salsa20 psutil) +FROM python:3.10-alpine3.16 AS python-pkg +RUN apk add build-base linux-headers RUN \ - apk add build-base && \ - pip3 install numpy salsa20 && \ + pip3 install numpy salsa20 psutil && \ cd /usr/local/lib/python*/site-packages/ && \ - mkdir /packages/ && mv ./*numpy* ./*salsa20* /packages/ && \ - rm -rf $(find /packages/ -name '__pycache__') - -# Combine shadowsocks dependencies -FROM python:3.10-alpine3.16 AS shadowsocks -COPY --from=ss-rust /tmp/ss-rust-* /release/ -COPY --from=ss-libev /tmp/ss-libev-* /release/ + mkdir /site-packages/ && mv ./*numpy* ./*salsa20* ./psutil* /site-packages/ && \ + rm -rf $(find /site-packages/ -name '__pycache__') COPY --from=ss-python /packages/ /site-packages/ -COPY --from=ss-bootstrap /tmp/ss-bootstrap-* /release/ -COPY --from=openssl /tmp/libcrypto.so* /release/ -COPY --from=salsa20 /packages/ /site-packages/ -RUN \ - PYTHON_PACKAGE="/usr/local/lib/$(ls /usr/local/lib/ | grep ^python)/site-packages" && \ - ln -s ${PYTHON_PACKAGE}/ssr-python/local.py /release/ssr-local && \ - ln -s ${PYTHON_PACKAGE}/ssr-python/server.py /release/ssr-server && \ - ln -s ${PYTHON_PACKAGE}/ss-python/local.py /release/ss-python-local && \ - ln -s ${PYTHON_PACKAGE}/ss-python/server.py /release/ss-python-server && \ - ln -s ${PYTHON_PACKAGE}/ss-python-legacy/local.py /release/ss-python-legacy-local && \ - ln -s ${PYTHON_PACKAGE}/ss-python-legacy/server.py /release/ss-python-legacy-server && \ - BZIP2=-9 tar cjf /release/packages.tar.bz2 ./site-packages/ +RUN BZIP2=-9 tar czf /packages.tar.gz ./site-packages/ # Compile sip003 plugins (part1 -> gcc & cargo) FROM rust:1.62-alpine3.16 AS plugin-1 @@ -443,32 +441,31 @@ RUN upx -9 /tmp/dnsproxy # Combine all release FROM python:3.10-alpine3.16 AS asset -COPY --from=shadowsocks /release/ /release/ -COPY --from=plugin /release/ /release/ -COPY --from=v2ray /tmp/v2* /release/ -COPY --from=xray /tmp/xray /release/ -COPY --from=trojan /tmp/trojan* /release/ -COPY --from=gost /tmp/gost* /release/ -COPY --from=brook /tmp/brook /release/ -COPY --from=clash /tmp/clash /release/ -COPY --from=snell /tmp/snell-* /release/ -COPY --from=hysteria /tmp/hysteria /release/ -COPY --from=naiveproxy /tmp/caddy /release/ -COPY --from=naiveproxy /tmp/naive /release/ -COPY --from=relaybaton /tmp/relaybaton /release/ -COPY --from=pingtunnel /tmp/pingtunnel /release/ -COPY --from=wireproxy /tmp/wireproxy /release/ -COPY --from=dnsproxy /tmp/dnsproxy /release/ +COPY --from=python-pkg /packages.tar.gz / RUN \ PACKAGE_DIR="/asset/usr/local/lib/$(ls /usr/local/lib/ | grep ^python)" && \ - mkdir -p ${PACKAGE_DIR}/ && tar xf /release/packages.tar.bz2 -C ${PACKAGE_DIR}/ && \ - mkdir -p /asset/lib/ && mv /release/*.so* /asset/lib/ && \ - rm -f /release/packages.tar.bz2 && \ - mv /release/ /asset/usr/bin/ + mkdir -p ${PACKAGE_DIR}/ && tar xf /packages.tar.gz -C ${PACKAGE_DIR}/ +COPY --from=openssl /tmp/libcrypto.so* /asset/lib/ +COPY --from=shadowsocks /release/ /asset/usr/bin/ +COPY --from=plugin /release/ /asset/usr/bin/ +COPY --from=v2ray /tmp/v2* /asset/usr/bin/ +COPY --from=xray /tmp/xray /asset/usr/bin/ +COPY --from=trojan /tmp/trojan* /asset/usr/bin/ +COPY --from=gost /tmp/gost* /asset/usr/bin/ +COPY --from=brook /tmp/brook /asset/usr/bin/ +COPY --from=clash /tmp/clash /asset/usr/bin/ +COPY --from=snell /tmp/snell-* /asset/usr/bin/ +COPY --from=hysteria /tmp/hysteria /asset/usr/bin/ +COPY --from=naiveproxy /tmp/caddy /asset/usr/bin/ +COPY --from=naiveproxy /tmp/naive /asset/usr/bin/ +COPY --from=relaybaton /tmp/relaybaton /asset/usr/bin/ +COPY --from=pingtunnel /tmp/pingtunnel /asset/usr/bin/ +COPY --from=wireproxy /tmp/wireproxy /asset/usr/bin/ +COPY --from=dnsproxy /tmp/dnsproxy /asset/usr/bin/ # Release docker image FROM python:3.10-alpine3.16 -COPY --from=asset /asset / RUN \ apk add --no-cache boost-program_options c-ares glib libev libsodium libstdc++ mbedtls pcre && \ pip3 --no-cache-dir install colorlog pysocks requests +COPY --from=asset /asset / diff --git a/test.py b/test.py index c24ba53..a014f99 100755 --- a/test.py +++ b/test.py @@ -5,10 +5,11 @@ import time import requests from Tester import Shadowsocks from Basis.Logger import logging - +from Basis.Functions import networkStatus def test(testObj: dict) -> None: logging.warning(testObj['title']) + logging.debug('network status -> %s' % networkStatus()) testObj['client'].start() testObj['server'].start()