mirror of
https://github.com/certbot/certbot.git
synced 2026-06-08 00:02:14 -04:00
Merge pull request #2690 from joohoi/2478
IPv6 support for Addr and correct parsing of IPv6 vhosts
This commit is contained in:
commit
6542c5787d
10 changed files with 158 additions and 38 deletions
|
|
@ -1,9 +0,0 @@
|
|||
<VirtualHost 173.192.30.7:80 [2607:f0d0:1005:99::3:1337]:80>
|
||||
DocumentRoot /xxxx/
|
||||
ServerName noodles.net.nz
|
||||
ServerAlias www.noodles.net.nz
|
||||
CustomLog ${APACHE_LOG_DIR}/domlogs/noodles.log combined
|
||||
<Directory "/xxxx/">
|
||||
AllowOverride All
|
||||
</Directory>
|
||||
</VirtualHost>
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
|
||||
<VirtualHost 173.192.30.7:443 [2607:f0d0:1005:99::3:1337]:443>
|
||||
DocumentRoot /xxxx/
|
||||
ServerName noodles.net.nz
|
||||
ServerAlias www.noodles.net.nz
|
||||
CustomLog ${APACHE_LOG_DIR}/domlogs/noodles.log combined
|
||||
<Directory "xxxx">
|
||||
AllowOverride All
|
||||
</Directory>
|
||||
|
||||
SSLEngine on
|
||||
|
||||
SSLHonorCipherOrder On
|
||||
SSLProtocol all -SSLv2 -SSLv3
|
||||
SSLCipherSuite "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH +aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS"
|
||||
|
||||
SSLCertificateFile /xxxx/noodles.net.nz.crt
|
||||
SSLCertificateKeyFile /xxxx/noodles.net.nz.key
|
||||
|
||||
Header set Strict-Transport-Security "max-age=31536000; preload"
|
||||
</VirtualHost>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<VirtualHost *:80 [::]:80>
|
||||
DocumentRoot /tmp
|
||||
ServerName example.com
|
||||
ServerAlias www.example.com
|
||||
CustomLog ${APACHE_LOG_DIR}/example.log combined
|
||||
<Directory "/tmp">
|
||||
AllowOverride All
|
||||
</Directory>
|
||||
</VirtualHost>
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<VirtualHost *:443 [::]:443>
|
||||
DocumentRoot /tmp
|
||||
ServerName example.com
|
||||
ServerAlias www.example.com
|
||||
CustomLog ${APACHE_LOG_DIR}/example.log combined
|
||||
<Directory "/tmp">
|
||||
AllowOverride All
|
||||
</Directory>
|
||||
|
||||
SSLEngine on
|
||||
|
||||
SSLHonorCipherOrder On
|
||||
SSLProtocol all -SSLv2 -SSLv3
|
||||
SSLCipherSuite "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH +aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS"
|
||||
|
||||
SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
|
||||
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
|
||||
</VirtualHost>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<VirtualHost [::]:80 *:80>
|
||||
DocumentRoot /tmp
|
||||
ServerName example.com
|
||||
ServerAlias www.example.com
|
||||
CustomLog ${APACHE_LOG_DIR}/example.log combined
|
||||
<Directory "/tmp">
|
||||
AllowOverride All
|
||||
</Directory>
|
||||
</VirtualHost>
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<VirtualHost [::]:443 *:443>
|
||||
DocumentRoot /tmp
|
||||
ServerName example.com
|
||||
ServerAlias www.example.com
|
||||
CustomLog ${APACHE_LOG_DIR}/example.log combined
|
||||
<Directory "/tmp">
|
||||
AllowOverride All
|
||||
</Directory>
|
||||
|
||||
SSLEngine on
|
||||
|
||||
SSLHonorCipherOrder On
|
||||
SSLProtocol all -SSLv2 -SSLv3
|
||||
SSLCipherSuite "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH +aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS"
|
||||
|
||||
SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
|
||||
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
|
||||
</VirtualHost>
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
<VirtualHost *:80>
|
||||
<VirtualHost *:80 [::]:80>
|
||||
|
||||
ServerName ip-172-30-0-17
|
||||
ServerAdmin webmaster@localhost
|
||||
|
|
|
|||
|
|
@ -133,8 +133,9 @@ def get_vh_truth(temp_dir, config_name):
|
|||
obj.VirtualHost(
|
||||
os.path.join(prefix, "000-default.conf"),
|
||||
os.path.join(aug_pre, "000-default.conf/VirtualHost"),
|
||||
set([obj.Addr.fromstring("*:80")]), False, True,
|
||||
"ip-172-30-0-17"),
|
||||
set([obj.Addr.fromstring("*:80"),
|
||||
obj.Addr.fromstring("[::]:80")]),
|
||||
False, True, "ip-172-30-0-17"),
|
||||
obj.VirtualHost(
|
||||
os.path.join(prefix, "letsencrypt.conf"),
|
||||
os.path.join(aug_pre, "letsencrypt.conf/VirtualHost"),
|
||||
|
|
|
|||
|
|
@ -104,14 +104,24 @@ class Addr(object):
|
|||
:param str port: port number or \*, or ""
|
||||
|
||||
"""
|
||||
def __init__(self, tup):
|
||||
def __init__(self, tup, ipv6=False):
|
||||
self.tup = tup
|
||||
self.ipv6 = ipv6
|
||||
|
||||
@classmethod
|
||||
def fromstring(cls, str_addr):
|
||||
"""Initialize Addr from string."""
|
||||
tup = str_addr.partition(':')
|
||||
return cls((tup[0], tup[2]))
|
||||
if str_addr.startswith('['):
|
||||
# ipv6 addresses starts with [
|
||||
endIndex = str_addr.rfind(']')
|
||||
host = str_addr[:endIndex + 1]
|
||||
port = ''
|
||||
if len(str_addr) > endIndex + 2 and str_addr[endIndex + 1] == ':':
|
||||
port = str_addr[endIndex + 2:]
|
||||
return cls((host, port), ipv6=True)
|
||||
else:
|
||||
tup = str_addr.partition(':')
|
||||
return cls((tup[0], tup[2]))
|
||||
|
||||
def __str__(self):
|
||||
if self.tup[1]:
|
||||
|
|
@ -120,7 +130,16 @@ class Addr(object):
|
|||
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, self.__class__):
|
||||
return self.tup == other.tup
|
||||
if self.ipv6:
|
||||
# compare normalized to take different
|
||||
# styles of representation into account
|
||||
return (other.ipv6 and
|
||||
self._normalize_ipv6(self.tup[0]) ==
|
||||
self._normalize_ipv6(other.tup[0]) and
|
||||
self.tup[1] == other.tup[1])
|
||||
else:
|
||||
return self.tup == other.tup
|
||||
|
||||
return False
|
||||
|
||||
def __hash__(self):
|
||||
|
|
@ -136,7 +155,44 @@ class Addr(object):
|
|||
|
||||
def get_addr_obj(self, port):
|
||||
"""Return new address object with same addr and new port."""
|
||||
return self.__class__((self.tup[0], port))
|
||||
return self.__class__((self.tup[0], port), self.ipv6)
|
||||
|
||||
def _normalize_ipv6(self, addr):
|
||||
"""Return IPv6 address in normalized form, helper function"""
|
||||
addr = addr.lstrip("[")
|
||||
addr = addr.rstrip("]")
|
||||
return self._explode_ipv6(addr)
|
||||
|
||||
def get_ipv6_exploded(self):
|
||||
"""Return IPv6 in normalized form"""
|
||||
if self.ipv6:
|
||||
return ":".join(self._normalize_ipv6(self.tup[0]))
|
||||
return ""
|
||||
|
||||
def _explode_ipv6(self, addr):
|
||||
"""Explode IPv6 address for comparison"""
|
||||
result = ['0', '0', '0', '0', '0', '0', '0', '0']
|
||||
addr_list = addr.split(":")
|
||||
if len(addr_list) > len(result):
|
||||
# too long, truncate
|
||||
addr_list = addr_list[0:len(result)]
|
||||
append_to_end = False
|
||||
for i in range(0, len(addr_list)):
|
||||
block = addr_list[i]
|
||||
if len(block) == 0:
|
||||
# encountered ::, so rest of the blocks should be
|
||||
# appended to the end
|
||||
append_to_end = True
|
||||
continue
|
||||
elif len(block) > 1:
|
||||
# remove leading zeros
|
||||
block = block.lstrip("0")
|
||||
if not append_to_end:
|
||||
result[i] = str(block)
|
||||
else:
|
||||
# count the location from the end using negative indices
|
||||
result[i-len(addr_list)] = str(block)
|
||||
return result
|
||||
|
||||
|
||||
class TLSSNI01(object):
|
||||
|
|
|
|||
|
|
@ -81,6 +81,11 @@ class AddrTest(unittest.TestCase):
|
|||
self.addr1 = Addr.fromstring("192.168.1.1")
|
||||
self.addr2 = Addr.fromstring("192.168.1.1:*")
|
||||
self.addr3 = Addr.fromstring("192.168.1.1:80")
|
||||
self.addr4 = Addr.fromstring("[fe00::1]")
|
||||
self.addr5 = Addr.fromstring("[fe00::1]:*")
|
||||
self.addr6 = Addr.fromstring("[fe00::1]:80")
|
||||
self.addr7 = Addr.fromstring("[fe00::1]:5")
|
||||
self.addr8 = Addr.fromstring("[fe00:1:2:3:4:5:6:7:8:9]:8080")
|
||||
|
||||
def test_fromstring(self):
|
||||
self.assertEqual(self.addr1.get_addr(), "192.168.1.1")
|
||||
|
|
@ -89,22 +94,49 @@ class AddrTest(unittest.TestCase):
|
|||
self.assertEqual(self.addr2.get_port(), "*")
|
||||
self.assertEqual(self.addr3.get_addr(), "192.168.1.1")
|
||||
self.assertEqual(self.addr3.get_port(), "80")
|
||||
self.assertEqual(self.addr4.get_addr(), "[fe00::1]")
|
||||
self.assertEqual(self.addr4.get_port(), "")
|
||||
self.assertEqual(self.addr5.get_addr(), "[fe00::1]")
|
||||
self.assertEqual(self.addr5.get_port(), "*")
|
||||
self.assertEqual(self.addr6.get_addr(), "[fe00::1]")
|
||||
self.assertEqual(self.addr6.get_port(), "80")
|
||||
self.assertEqual(self.addr6.get_ipv6_exploded(),
|
||||
"fe00:0:0:0:0:0:0:1")
|
||||
self.assertEqual(self.addr1.get_ipv6_exploded(),
|
||||
"")
|
||||
self.assertEqual(self.addr7.get_port(), "5")
|
||||
self.assertEqual(self.addr8.get_ipv6_exploded(),
|
||||
"fe00:1:2:3:4:5:6:7")
|
||||
|
||||
def test_str(self):
|
||||
self.assertEqual(str(self.addr1), "192.168.1.1")
|
||||
self.assertEqual(str(self.addr2), "192.168.1.1:*")
|
||||
self.assertEqual(str(self.addr3), "192.168.1.1:80")
|
||||
self.assertEqual(str(self.addr4), "[fe00::1]")
|
||||
self.assertEqual(str(self.addr5), "[fe00::1]:*")
|
||||
self.assertEqual(str(self.addr6), "[fe00::1]:80")
|
||||
|
||||
def test_get_addr_obj(self):
|
||||
self.assertEqual(str(self.addr1.get_addr_obj("443")), "192.168.1.1:443")
|
||||
self.assertEqual(str(self.addr2.get_addr_obj("")), "192.168.1.1")
|
||||
self.assertEqual(str(self.addr1.get_addr_obj("*")), "192.168.1.1:*")
|
||||
self.assertEqual(str(self.addr4.get_addr_obj("443")), "[fe00::1]:443")
|
||||
self.assertEqual(str(self.addr5.get_addr_obj("")), "[fe00::1]")
|
||||
self.assertEqual(str(self.addr4.get_addr_obj("*")), "[fe00::1]:*")
|
||||
|
||||
def test_eq(self):
|
||||
self.assertEqual(self.addr1, self.addr2.get_addr_obj(""))
|
||||
self.assertNotEqual(self.addr1, self.addr2)
|
||||
self.assertFalse(self.addr1 == 3333)
|
||||
|
||||
self.assertEqual(self.addr4, self.addr4.get_addr_obj(""))
|
||||
self.assertNotEqual(self.addr4, self.addr5)
|
||||
self.assertFalse(self.addr4 == 3333)
|
||||
from letsencrypt.plugins.common import Addr
|
||||
self.assertEqual(self.addr4, Addr.fromstring("[fe00:0:0::1]"))
|
||||
self.assertEqual(self.addr4, Addr.fromstring("[fe00:0::0:0:1]"))
|
||||
|
||||
|
||||
def test_set_inclusion(self):
|
||||
from letsencrypt.plugins.common import Addr
|
||||
set_a = set([self.addr1, self.addr2])
|
||||
|
|
@ -114,6 +146,13 @@ class AddrTest(unittest.TestCase):
|
|||
|
||||
self.assertEqual(set_a, set_b)
|
||||
|
||||
set_c = set([self.addr4, self.addr5])
|
||||
addr4b = Addr.fromstring("[fe00::1]")
|
||||
addr5b = Addr.fromstring("[fe00::1]:*")
|
||||
set_d = set([addr4b, addr5b])
|
||||
|
||||
self.assertEqual(set_c, set_d)
|
||||
|
||||
|
||||
class TLSSNI01Test(unittest.TestCase):
|
||||
"""Tests for letsencrypt.plugins.common.TLSSNI01."""
|
||||
|
|
|
|||
Loading…
Reference in a new issue