tests-httpd: add proxy tests

for direct and tunneling checks on http: and https:

Closes #10519
This commit is contained in:
Stefan Eissing 2023-02-15 12:39:46 +01:00 committed by Daniel Stenberg
parent 6841f2ed5f
commit 216e4b1fb6
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
4 changed files with 113 additions and 37 deletions

View File

@ -34,11 +34,13 @@ apachectl = @APACHECTL@
http_port = 5001
https_port = 5002
h3_port = 5002
proxy_port = 5004
proxys_port = 5005
[nghttpx]
nghttpx = @HTTPD_NGHTTPX@
[caddy]
caddy = @CADDY@
http_port = 5003
https_port = 5004
http_port = 5010
https_port = 5011

View File

@ -45,26 +45,89 @@ class TestProxy:
os.makedirs(push_dir)
# download via http: proxy (no tunnel)
def test_10_01_http_get(self, env: Env, httpd, repeat):
def test_10_01_proxy_http(self, env: Env, httpd, repeat):
curl = CurlClient(env=env)
url = f'http://localhost:{env.http_port}/data.json'
r = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True,
extra_args=[
'--proxy', f'http://{env.proxy_domain}:{env.http_port}/',
'--resolve', f'{env.proxy_domain}:{env.http_port}:127.0.0.1',
'--proxy', f'http://{env.proxy_domain}:{env.proxy_port}/',
'--resolve', f'{env.proxy_domain}:{env.proxy_port}:127.0.0.1',
])
assert r.exit_code == 0
r.check_stats(count=1, exp_status=200)
# download via https: proxy (no tunnel)
def test_10_02_http_get(self, env: Env, httpd, repeat):
def test_10_02_proxy_https(self, env: Env, httpd, repeat):
curl = CurlClient(env=env)
url = f'http://localhost:{env.http_port}/data.json'
r = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True,
extra_args=[
'--proxy', f'https://{env.proxy_domain}:{env.https_port}/',
'--resolve', f'{env.proxy_domain}:{env.https_port}:127.0.0.1',
'--proxy', f'https://{env.proxy_domain}:{env.proxys_port}/',
'--resolve', f'{env.proxy_domain}:{env.proxys_port}:127.0.0.1',
'--proxy-cacert', env.ca.cert_file,
])
assert r.exit_code == 0
r.check_stats(count=1, exp_status=200)
# download http: via http: proxytunnel
def test_10_03_proxytunnel_http(self, env: Env, httpd, repeat):
curl = CurlClient(env=env)
url = f'http://localhost:{env.http_port}/data.json'
r = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True,
extra_args=[
'--proxytunnel',
'--proxy', f'http://{env.proxy_domain}:{env.proxy_port}/',
'--resolve', f'{env.proxy_domain}:{env.proxy_port}:127.0.0.1',
])
assert r.exit_code == 0
r.check_stats(count=1, exp_status=200)
# download http: via https: proxytunnel
def test_10_04_proxy_https(self, env: Env, httpd, repeat):
curl = CurlClient(env=env)
url = f'http://localhost:{env.http_port}/data.json'
r = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True,
extra_args=[
'--proxytunnel',
'--proxy', f'https://{env.proxy_domain}:{env.proxys_port}/',
'--resolve', f'{env.proxy_domain}:{env.proxys_port}:127.0.0.1',
'--proxy-cacert', env.ca.cert_file,
])
assert r.exit_code == 0
r.check_stats(count=1, exp_status=200)
# download https: with proto via http: proxytunnel
@pytest.mark.parametrize("proto", ['http/1.1', 'h2'])
def test_10_05_proxytunnel_http(self, env: Env, httpd, proto, repeat):
curl = CurlClient(env=env)
url = f'https://localhost:{env.https_port}/data.json'
r = curl.http_download(urls=[url], alpn_proto=proto, with_stats=True,
with_headers=True,
extra_args=[
'--proxytunnel',
'--proxy', f'http://{env.proxy_domain}:{env.proxy_port}/',
'--resolve', f'{env.proxy_domain}:{env.proxy_port}:127.0.0.1',
])
assert r.exit_code == 0
r.check_stats(count=1, exp_status=200)
exp_proto = 'HTTP/2' if proto == 'h2' else 'HTTP/1.1'
assert r.response['protocol'] == exp_proto
# download https: with proto via https: proxytunnel
@pytest.mark.parametrize("proto", ['http/1.1', 'h2'])
def test_10_06_proxy_https(self, env: Env, httpd, proto, repeat):
curl = CurlClient(env=env)
url = f'https://localhost:{env.https_port}/data.json'
r = curl.http_download(urls=[url], alpn_proto=proto, with_stats=True,
with_headers=True,
extra_args=[
'--proxytunnel',
'--proxy', f'https://{env.proxy_domain}:{env.proxys_port}/',
'--resolve', f'{env.proxy_domain}:{env.proxys_port}:127.0.0.1',
'--proxy-cacert', env.ca.cert_file,
])
assert r.exit_code == 0
r.check_stats(count=1, exp_status=200)
exp_proto = 'HTTP/2' if proto == 'h2' else 'HTTP/1.1'
assert r.response['protocol'] == exp_proto

View File

@ -97,6 +97,8 @@ class EnvConfig:
self.http_port = self.config['test']['http_port']
self.https_port = self.config['test']['https_port']
self.proxy_port = self.config['test']['proxy_port']
self.proxys_port = self.config['test']['proxys_port']
self.h3_port = self.config['test']['h3_port']
self.httpd = self.config['httpd']['httpd']
self.apachectl = self.config['httpd']['apachectl']
@ -115,7 +117,7 @@ class EnvConfig:
self.domain2 = f"two.{self.tld}"
self.proxy_domain = f"proxy.{self.tld}"
self.cert_specs = [
CertificateSpec(domains=[self.domain1], key_type='rsa2048'),
CertificateSpec(domains=[self.domain1, 'localhost'], key_type='rsa2048'),
CertificateSpec(domains=[self.domain2], key_type='rsa2048'),
CertificateSpec(domains=[self.proxy_domain], key_type='rsa2048'),
CertificateSpec(name="clientsX", sub_specs=[
@ -300,7 +302,6 @@ class Env:
def proxy_domain(self) -> str:
return self.CONFIG.proxy_domain
@property
def http_port(self) -> str:
return self.CONFIG.http_port
@ -313,6 +314,14 @@ class Env:
def h3_port(self) -> str:
return self.CONFIG.h3_port
@property
def proxy_port(self) -> str:
return self.CONFIG.proxy_port
@property
def proxys_port(self) -> str:
return self.CONFIG.proxys_port
@property
def caddy(self) -> str:
return self.CONFIG.caddy

View File

@ -226,6 +226,8 @@ class Httpd:
f'H2MaxWorkers 128',
f'Listen {self.env.http_port}',
f'Listen {self.env.https_port}',
f'Listen {self.env.proxy_port}',
f'Listen {self.env.proxys_port}',
f'TypesConfig "{self._conf_dir}/mime.types',
]
conf.extend([ # plain http host for domain1
@ -239,33 +241,6 @@ class Httpd:
f'</VirtualHost>',
f'',
])
conf.extend([ # http forward proxy
f'<VirtualHost *:{self.env.http_port}>',
f' ServerName {proxy_domain}',
f' Protocols http/1.1',
f' ProxyRequests On',
f' ProxyVia On',
f' AllowCONNECT {self.env.http_port} {self.env.https_port}',
f' <Proxy "*">',
f' Require ip 127.0.0.1',
f' </Proxy>',
f'</VirtualHost>',
])
conf.extend([ # https forward proxy
f'<VirtualHost *:{self.env.https_port}>',
f' ServerName {proxy_domain}',
f' Protocols http/1.1',
f' SSLEngine on',
f' SSLCertificateFile {proxy_creds.cert_file}',
f' SSLCertificateKeyFile {proxy_creds.pkey_file}',
f' ProxyRequests On',
f' ProxyVia On',
f' AllowCONNECT {self.env.http_port} {self.env.https_port}',
f' <Proxy "*">',
f' Require ip 127.0.0.1',
f' </Proxy>',
f'</VirtualHost>',
])
conf.extend([ # https host for domain1, h1 + h2
f'<VirtualHost *:{self.env.https_port}>',
f' ServerName {domain1}',
@ -298,6 +273,33 @@ class Httpd:
f'</VirtualHost>',
f'',
])
conf.extend([ # http forward proxy
f'<VirtualHost *:{self.env.proxy_port}>',
f' ServerName {proxy_domain}',
f' Protocols h2c, http/1.1',
f' ProxyRequests On',
f' ProxyVia On',
f' AllowCONNECT {self.env.http_port} {self.env.https_port}',
f' <Proxy "*">',
f' Require ip 127.0.0.1',
f' </Proxy>',
f'</VirtualHost>',
])
conf.extend([ # https forward proxy
f'<VirtualHost *:{self.env.proxys_port}>',
f' ServerName {proxy_domain}',
f' Protocols h2, http/1.1',
f' SSLEngine on',
f' SSLCertificateFile {proxy_creds.cert_file}',
f' SSLCertificateKeyFile {proxy_creds.pkey_file}',
f' ProxyRequests On',
f' ProxyVia On',
f' AllowCONNECT {self.env.http_port} {self.env.https_port}',
f' <Proxy "*">',
f' Require ip 127.0.0.1',
f' </Proxy>',
f'</VirtualHost>',
])
fd.write("\n".join(conf))
with open(os.path.join(self._conf_dir, 'mime.types'), 'w') as fd:
fd.write("\n".join([