dns-rfc2136: use TCP to query SOA records (#7503)

* Use tcp query on dns-rfc2136 plugin

To improve network robust; fixes #7502.

* Update CHANGELOG.md

* Fix dns-rfc2136 test cases

* Add UDP fallback to dns-rfc2136
This commit is contained in:
Shell Chen 2019-11-08 01:37:12 +08:00 committed by Adrien Ferrand
parent b84edfd39a
commit f4f16605ed
3 changed files with 23 additions and 4 deletions

View file

@ -61,6 +61,7 @@ More details about these changes can be found on our GitHub repo.
* acme.standalone.BaseRequestHandlerWithLogging and
acme.standalone.simple_tls_sni_01_server have been deprecated and will be
removed in a future release of the library.
* certbot-dns-rfc2136 now use TCP to query SOA records.
### Fixed

View file

@ -206,7 +206,11 @@ class _RFC2136Client(object):
request.flags ^= dns.flags.RD
try:
response = dns.query.udp(request, self.server, port=self.port)
try:
response = dns.query.tcp(request, self.server, port=self.port)
except OSError as e:
logger.debug('TCP query failed, fallback to UDP: %s', e)
response = dns.query.udp(request, self.server, port=self.port)
rcode = response.rcode()
# Authoritative Answer bit should be set

View file

@ -162,7 +162,7 @@ class RFC2136ClientTest(unittest.TestCase):
self.rfc2136_client._find_domain,
'foo.bar.'+DOMAIN)
@mock.patch("dns.query.udp")
@mock.patch("dns.query.tcp")
def test_query_soa_found(self, query_mock):
query_mock.return_value = mock.MagicMock(answer=[mock.MagicMock()], flags=dns.flags.AA)
query_mock.return_value.rcode.return_value = dns.rcode.NOERROR
@ -173,7 +173,7 @@ class RFC2136ClientTest(unittest.TestCase):
query_mock.assert_called_with(mock.ANY, SERVER, port=PORT)
self.assertTrue(result)
@mock.patch("dns.query.udp")
@mock.patch("dns.query.tcp")
def test_query_soa_not_found(self, query_mock):
query_mock.return_value.rcode.return_value = dns.rcode.NXDOMAIN
@ -183,7 +183,7 @@ class RFC2136ClientTest(unittest.TestCase):
query_mock.assert_called_with(mock.ANY, SERVER, port=PORT)
self.assertFalse(result)
@mock.patch("dns.query.udp")
@mock.patch("dns.query.tcp")
def test_query_soa_wraps_errors(self, query_mock):
query_mock.side_effect = Exception
@ -193,6 +193,20 @@ class RFC2136ClientTest(unittest.TestCase):
self.rfc2136_client._query_soa,
DOMAIN)
@mock.patch("dns.query.udp")
@mock.patch("dns.query.tcp")
def test_query_soa_fallback_to_udp(self, tcp_mock, udp_mock):
tcp_mock.side_effect = OSError
udp_mock.return_value = mock.MagicMock(answer=[mock.MagicMock()], flags=dns.flags.AA)
udp_mock.return_value.rcode.return_value = dns.rcode.NOERROR
# _query_soa | pylint: disable=protected-access
result = self.rfc2136_client._query_soa(DOMAIN)
tcp_mock.assert_called_with(mock.ANY, SERVER, port=PORT)
udp_mock.assert_called_with(mock.ANY, SERVER, port=PORT)
self.assertTrue(result)
if __name__ == "__main__":
unittest.main() # pragma: no cover