mirror of
https://github.com/3proxy/3proxy.git
synced 2026-11-07 02:05:49 +08:00
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
C/C++ CI cmake / ubuntu-latest (wolfSSL) (push) Has been cancelled
3proxy --help (and the usage message of a bad invocation) now lists what the build was made with: TLS and its backend, RADIUS, PCRE, IPv6, UNIX sockets, the built-in HTTP server, transparency, ODBC and the optional proxy services. The test runner reads the list before the first case and the cases state the features they need with t.skip_unless(), so a build without a feature skips its cases instead of failing them; a binary too old to report anything skips the cases with needs and runs the rest.
121 lines
4.0 KiB
Python
121 lines
4.0 KiB
Python
"""The system's name servers and hosts file as the default resolver: with
|
|
no nserver in a configuration, names in the hosts file are answered from
|
|
it; with nserver lines it is not. Each service resolves names the way the
|
|
last of defaultresolve, sysresolve and fakeresolve before it says."""
|
|
|
|
import os
|
|
import re
|
|
import sys
|
|
import time
|
|
|
|
|
|
def hosts_path():
|
|
if sys.platform == "win32":
|
|
return os.path.join(os.environ.get("SystemRoot", r"C:\Windows"),
|
|
"System32", "drivers", "etc", "hosts")
|
|
return "/etc/hosts"
|
|
|
|
|
|
def hosts_localhost():
|
|
"""Whether the hosts file maps localhost to 127.0.0.1 itself."""
|
|
try:
|
|
with open(hosts_path(), errors="replace") as f:
|
|
for line in f:
|
|
words = line.split("#", 1)[0].split()
|
|
if len(words) > 1 and words[0] == "127.0.0.1" and "localhost" in [w.lower() for w in words[1:]]:
|
|
return True
|
|
except OSError:
|
|
pass
|
|
return False
|
|
|
|
|
|
def system_nameserver():
|
|
"""Whether there is a name server for 3proxy to find: resolv.conf has
|
|
one, or on Windows the registry is taken to."""
|
|
if sys.platform == "win32":
|
|
return True
|
|
try:
|
|
with open("/etc/resolv.conf") as f:
|
|
return any(re.match(r"nameserver\s+[0-9a-fA-F.:]+\s*$", l.split("#")[0]) for l in f)
|
|
except OSError:
|
|
return False
|
|
|
|
|
|
def wait(t, port, name):
|
|
deadline = time.time() + 5
|
|
while time.time() < deadline:
|
|
if t.dns_query(port, name):
|
|
return
|
|
|
|
|
|
def run(t):
|
|
if not t.skip_unless("httpsrv"):
|
|
return
|
|
if not hosts_localhost() or not system_nameserver():
|
|
t.skip("no localhost in the hosts file, or no system name server")
|
|
return
|
|
|
|
port = t.free_port()
|
|
t.start("sysdns", f"""
|
|
log
|
|
flush
|
|
auth iponly
|
|
allow *
|
|
dnspr -p{port}
|
|
""")
|
|
wait(t, port, "localhost")
|
|
t.eq(["127.0.0.1"], t.dns_query(port, "localhost"),
|
|
"without nserver, a name of the hosts file is answered from it")
|
|
t.eq(["127.0.0.1"], t.dns_query(port, "LocalHost"),
|
|
"whatever its case")
|
|
|
|
# with a name server configured, one that answers nothing, the hosts
|
|
# file is not used
|
|
other = t.free_port()
|
|
t.start("sysdns_nserver", f"""
|
|
log
|
|
flush
|
|
nserver 127.0.0.1:{t.free_port()}
|
|
nscache 1024
|
|
auth iponly
|
|
allow *
|
|
dnspr -p{other}
|
|
""")
|
|
wait(t, other, "localhost")
|
|
t.ne(["127.0.0.1"], t.dns_query(other, "localhost") or [],
|
|
"with nserver, the hosts file is not used")
|
|
|
|
# each service resolves the way the command before it says: fake (to
|
|
# 127.0.0.2, where the server is not), the system routines (no
|
|
# nsrecord) or the default (the system's name servers, and nsrecord)
|
|
fake, system, default, srv = t.free_port(), t.free_port(), t.free_port(), t.free_port()
|
|
t.start("sysdns_modes", f"""
|
|
log
|
|
nscache 1024
|
|
nsrecord only3proxy.test 127.0.0.1
|
|
flush
|
|
auth iponly
|
|
allow *
|
|
fakeresolve
|
|
proxy -p{fake}
|
|
sysresolve
|
|
proxy -p{system}
|
|
defaultresolve
|
|
proxy -p{default}
|
|
flush
|
|
auth iponly
|
|
allow *
|
|
http echo * /echo**
|
|
httpsrv -i127.0.0.1 -p{srv}
|
|
""", ports=[fake, system, default, srv])
|
|
t.eq(200, t.http(f"http://localhost:{srv}/echo", proxy=f"127.0.0.1:{default}").status,
|
|
"defaultresolve: a name of the hosts file resolves")
|
|
t.eq(200, t.http(f"http://only3proxy.test:{srv}/echo", proxy=f"127.0.0.1:{default}").status,
|
|
"and an nsrecord name")
|
|
t.eq(200, t.http(f"http://localhost:{srv}/echo", proxy=f"127.0.0.1:{system}").status,
|
|
"sysresolve: names resolve through the system routines")
|
|
t.ne(200, t.http(f"http://only3proxy.test:{srv}/echo", proxy=f"127.0.0.1:{system}").status,
|
|
"which know no nsrecord name")
|
|
t.ne(200, t.http(f"http://localhost:{srv}/echo", proxy=f"127.0.0.1:{fake}").status,
|
|
"fakeresolve: every name is 127.0.0.2, in a service before the others")
|