[Group.of.nepali.translators] [Bug 1811471] Re: local resolver stub fails to handle multiple TCP dns queries
** No longer affects: systemd (Ubuntu Trusty) ** No longer affects: systemd (Ubuntu Xenial) -- You received this bug notification because you are a member of नेपाली भाषा समायोजकहरुको समूह, which is subscribed to Xenial. Matching subscriptions: Ubuntu 16.04 Bugs https://bugs.launchpad.net/bugs/1811471 Title: local resolver stub fails to handle multiple TCP dns queries Status in systemd: Fix Released Status in systemd package in Ubuntu: Fix Released Status in systemd source package in Bionic: Fix Released Status in systemd source package in Cosmic: Fix Released Status in systemd source package in Disco: Fix Released Bug description: [Impact] The systemd local 'stub' resolver handles all local DNS queries (by default configuration used in Ubuntu), and essentially proxies all requests to its configured upstream DNS resolvers. Most local DNS resolution by applications uses glibc's getaddrinfo() function. This function is configured in various ways by the /etc/resolv.conf file, which tells glibc what nameserver/resolver to contact as well as how to talk to the name server. By default, glibc performs UDP DNS queries, with a single DNS query per UDP packet. The UDP packet size is limited per DNS spec to 512 bytes. For some DNS lookups, a 512 byte UDP packet is not large enough to contain the entire response - for example, an A record lookup with a large number (e.g. 30) of A record addresses. This number of A record entries is possible in some cases of load balancing. When the DNS UDP response size is larger than 512 bytes, the server puts as much response as it can into the DNS UDP response, and marks the "trunacted" flag. This lets glibc know that the DNS UDP packet did not contain the entire response for all the A records. When glibc sees a UDP response that is "trunacted", by default it ignores the contents of that response and issues a new DNS query, using TCP instead of UDP. The TCP packet size has a higher size limit (though see bug 1804487 which is a bug in systemd's max-sizing of TCP DNS packets), and so *should* allow glibc to receive the entire DNS response. However, glibc issues DNS queries for both A and records. When it uses UDP, those DNS queries are separate (i.e. one UDP DNS packet with a single A query, and one UDP DNS packet with a single query). When glibc uses TCP, it puts both DNS queries into a single TCP DNS packet - the RFC refers to this as "pipelining" (https://tools.ietf.org/html/rfc7766#section-6.2.1.1) and states that clients SHOULD do this, and that servers MUST expect to receive pipelined queries and SHOULD respond to all of them. (Technically pipelining can be separate DNS queries, one per TCP packet, but both using the same TCP connection - but the clear intention of pipelining is to improve TCP performance, and putting both DNS queries into a single TCP packet is clearly more performant than using separate TCP packets). Unfortunately, systemd's local stub resolver has only very basic support for TCP DNS, and it handles TCP DNS queries almost identically to UDP DNS queries - it reads the DNS query 2-byte header (containing the length of the query data), reads in the single DNS query data, performs lookup and sends a response to that DNS query, and closes the TCP connection. It does not check for "pipelined" queries in the TCP connection. That would be bad enough, as glibc is (rightly) expecting a response to both its A and queries; however what glibc gets is a TCP connection-reset error. That is because the local systemd stub resolver has closed its TCP socket while input data was still pending (i.e. it never even read the second pipelined DNS query). When the kernel sees unread input bytes in a TCP connection that is closed, it sends a TCP RST to the peer (i.e. glibc) and when the kernel sees the RST, it dumps all data in its socket buffer and passes the ECONNRESET error up to the application. So glibc gets nothing besides a connection reset error. Note also that even if the systemd local stub resolver's socket flushes its input buffer before closing the TCP connection (which will avoid the TCP RST), glibc still expects responses to both its A and queries before systemd closes the TCP connection, and so a simple change to systemd to flush the input buffer is not enough to fix the bug (and would also not actually fix the bug since glibc would never get the response). [Test Case] This can be reproduced on any system using a local systemd stub resolver, when using an application that uses getaddrinfo() - such as ssh, telnet, ping, etc - or with a simple C program that uses getaddrinfo(). The dns name looked up must have enough A records to overflow the 512 byte maximum for a UDP DNS packet; e.g.: $ ping testing.irongiantdesign.com ping: testing.irongiantdesign.com: Temporary
[Group.of.nepali.translators] [Bug 1811471] Re: local resolver stub fails to handle multiple TCP dns queries
** Changed in: systemd Status: New => Fix Released -- You received this bug notification because you are a member of नेपाली भाषा समायोजकहरुको समूह, which is subscribed to Xenial. Matching subscriptions: Ubuntu 16.04 Bugs https://bugs.launchpad.net/bugs/1811471 Title: local resolver stub fails to handle multiple TCP dns queries Status in systemd: Fix Released Status in systemd package in Ubuntu: Fix Released Status in systemd source package in Trusty: Invalid Status in systemd source package in Xenial: Invalid Status in systemd source package in Bionic: Fix Released Status in systemd source package in Cosmic: Fix Released Status in systemd source package in Disco: Fix Released Bug description: [Impact] The systemd local 'stub' resolver handles all local DNS queries (by default configuration used in Ubuntu), and essentially proxies all requests to its configured upstream DNS resolvers. Most local DNS resolution by applications uses glibc's getaddrinfo() function. This function is configured in various ways by the /etc/resolv.conf file, which tells glibc what nameserver/resolver to contact as well as how to talk to the name server. By default, glibc performs UDP DNS queries, with a single DNS query per UDP packet. The UDP packet size is limited per DNS spec to 512 bytes. For some DNS lookups, a 512 byte UDP packet is not large enough to contain the entire response - for example, an A record lookup with a large number (e.g. 30) of A record addresses. This number of A record entries is possible in some cases of load balancing. When the DNS UDP response size is larger than 512 bytes, the server puts as much response as it can into the DNS UDP response, and marks the "trunacted" flag. This lets glibc know that the DNS UDP packet did not contain the entire response for all the A records. When glibc sees a UDP response that is "trunacted", by default it ignores the contents of that response and issues a new DNS query, using TCP instead of UDP. The TCP packet size has a higher size limit (though see bug 1804487 which is a bug in systemd's max-sizing of TCP DNS packets), and so *should* allow glibc to receive the entire DNS response. However, glibc issues DNS queries for both A and records. When it uses UDP, those DNS queries are separate (i.e. one UDP DNS packet with a single A query, and one UDP DNS packet with a single query). When glibc uses TCP, it puts both DNS queries into a single TCP DNS packet - the RFC refers to this as "pipelining" (https://tools.ietf.org/html/rfc7766#section-6.2.1.1) and states that clients SHOULD do this, and that servers MUST expect to receive pipelined queries and SHOULD respond to all of them. (Technically pipelining can be separate DNS queries, one per TCP packet, but both using the same TCP connection - but the clear intention of pipelining is to improve TCP performance, and putting both DNS queries into a single TCP packet is clearly more performant than using separate TCP packets). Unfortunately, systemd's local stub resolver has only very basic support for TCP DNS, and it handles TCP DNS queries almost identically to UDP DNS queries - it reads the DNS query 2-byte header (containing the length of the query data), reads in the single DNS query data, performs lookup and sends a response to that DNS query, and closes the TCP connection. It does not check for "pipelined" queries in the TCP connection. That would be bad enough, as glibc is (rightly) expecting a response to both its A and queries; however what glibc gets is a TCP connection-reset error. That is because the local systemd stub resolver has closed its TCP socket while input data was still pending (i.e. it never even read the second pipelined DNS query). When the kernel sees unread input bytes in a TCP connection that is closed, it sends a TCP RST to the peer (i.e. glibc) and when the kernel sees the RST, it dumps all data in its socket buffer and passes the ECONNRESET error up to the application. So glibc gets nothing besides a connection reset error. Note also that even if the systemd local stub resolver's socket flushes its input buffer before closing the TCP connection (which will avoid the TCP RST), glibc still expects responses to both its A and queries before systemd closes the TCP connection, and so a simple change to systemd to flush the input buffer is not enough to fix the bug (and would also not actually fix the bug since glibc would never get the response). [Test Case] This can be reproduced on any system using a local systemd stub resolver, when using an application that uses getaddrinfo() - such as ssh, telnet, ping, etc - or with a simple C program that uses getaddrinfo(). The dns name looked up must have enough A records to overflow the 512 byte maximum for a UDP DNS packet; e.g.: $ ping
[Group.of.nepali.translators] [Bug 1811471] Re: local resolver stub fails to handle multiple TCP dns queries
This bug was fixed in the package systemd - 239-7ubuntu10.7 --- systemd (239-7ubuntu10.7) cosmic; urgency=medium * d/p/resolve-enable-EDNS0-towards-the-127.0.0.53-stub-res.patch getaddrinfo() failures when fallback to dns tcp queries, so enable edns0 in resolv.conf (LP: #1811471) [ Victor Tapia ] * d/p/resolved-Increase-size-of-TCP-stub-replies.patch dns failures with edns0 disabled and truncated response (LP: #1804487) -- Dan Streetman Tue, 29 Jan 2019 14:19:39 -0500 ** Changed in: systemd (Ubuntu Cosmic) Status: Fix Committed => Fix Released -- You received this bug notification because you are a member of नेपाली भाषा समायोजकहरुको समूह, which is subscribed to Xenial. Matching subscriptions: Ubuntu 16.04 Bugs https://bugs.launchpad.net/bugs/1811471 Title: local resolver stub fails to handle multiple TCP dns queries Status in systemd: New Status in systemd package in Ubuntu: Fix Released Status in systemd source package in Trusty: Invalid Status in systemd source package in Xenial: Invalid Status in systemd source package in Bionic: Fix Released Status in systemd source package in Cosmic: Fix Released Status in systemd source package in Disco: Fix Released Bug description: [Impact] The systemd local 'stub' resolver handles all local DNS queries (by default configuration used in Ubuntu), and essentially proxies all requests to its configured upstream DNS resolvers. Most local DNS resolution by applications uses glibc's getaddrinfo() function. This function is configured in various ways by the /etc/resolv.conf file, which tells glibc what nameserver/resolver to contact as well as how to talk to the name server. By default, glibc performs UDP DNS queries, with a single DNS query per UDP packet. The UDP packet size is limited per DNS spec to 512 bytes. For some DNS lookups, a 512 byte UDP packet is not large enough to contain the entire response - for example, an A record lookup with a large number (e.g. 30) of A record addresses. This number of A record entries is possible in some cases of load balancing. When the DNS UDP response size is larger than 512 bytes, the server puts as much response as it can into the DNS UDP response, and marks the "trunacted" flag. This lets glibc know that the DNS UDP packet did not contain the entire response for all the A records. When glibc sees a UDP response that is "trunacted", by default it ignores the contents of that response and issues a new DNS query, using TCP instead of UDP. The TCP packet size has a higher size limit (though see bug 1804487 which is a bug in systemd's max-sizing of TCP DNS packets), and so *should* allow glibc to receive the entire DNS response. However, glibc issues DNS queries for both A and records. When it uses UDP, those DNS queries are separate (i.e. one UDP DNS packet with a single A query, and one UDP DNS packet with a single query). When glibc uses TCP, it puts both DNS queries into a single TCP DNS packet - the RFC refers to this as "pipelining" (https://tools.ietf.org/html/rfc7766#section-6.2.1.1) and states that clients SHOULD do this, and that servers MUST expect to receive pipelined queries and SHOULD respond to all of them. (Technically pipelining can be separate DNS queries, one per TCP packet, but both using the same TCP connection - but the clear intention of pipelining is to improve TCP performance, and putting both DNS queries into a single TCP packet is clearly more performant than using separate TCP packets). Unfortunately, systemd's local stub resolver has only very basic support for TCP DNS, and it handles TCP DNS queries almost identically to UDP DNS queries - it reads the DNS query 2-byte header (containing the length of the query data), reads in the single DNS query data, performs lookup and sends a response to that DNS query, and closes the TCP connection. It does not check for "pipelined" queries in the TCP connection. That would be bad enough, as glibc is (rightly) expecting a response to both its A and queries; however what glibc gets is a TCP connection-reset error. That is because the local systemd stub resolver has closed its TCP socket while input data was still pending (i.e. it never even read the second pipelined DNS query). When the kernel sees unread input bytes in a TCP connection that is closed, it sends a TCP RST to the peer (i.e. glibc) and when the kernel sees the RST, it dumps all data in its socket buffer and passes the ECONNRESET error up to the application. So glibc gets nothing besides a connection reset error. Note also that even if the systemd local stub resolver's socket flushes its input buffer before closing the TCP connection (which will avoid the TCP RST), glibc still expects responses to both its A and queries before systemd closes the TCP connection, and so a simple
[Group.of.nepali.translators] [Bug 1811471] Re: local resolver stub fails to handle multiple TCP dns queries
This bug was fixed in the package systemd - 237-3ubuntu10.12 --- systemd (237-3ubuntu10.12) bionic; urgency=medium * d/p/resolve-enable-EDNS0-towards-the-127.0.0.53-stub-res.patch getaddrinfo() failures when fallback to dns tcp queries, so enable edns0 in resolv.conf (LP: #1811471) [ Victor Tapia ] * d/p/resolved-Increase-size-of-TCP-stub-replies.patch dns failures with edns0 disabled and truncated response (LP: #1804487) -- Dan Streetman Tue, 29 Jan 2019 14:26:48 -0500 ** Changed in: systemd (Ubuntu Bionic) Status: Fix Committed => Fix Released -- You received this bug notification because you are a member of नेपाली भाषा समायोजकहरुको समूह, which is subscribed to Xenial. Matching subscriptions: Ubuntu 16.04 Bugs https://bugs.launchpad.net/bugs/1811471 Title: local resolver stub fails to handle multiple TCP dns queries Status in systemd: New Status in systemd package in Ubuntu: Fix Released Status in systemd source package in Trusty: Invalid Status in systemd source package in Xenial: Invalid Status in systemd source package in Bionic: Fix Released Status in systemd source package in Cosmic: Fix Released Status in systemd source package in Disco: Fix Released Bug description: [Impact] The systemd local 'stub' resolver handles all local DNS queries (by default configuration used in Ubuntu), and essentially proxies all requests to its configured upstream DNS resolvers. Most local DNS resolution by applications uses glibc's getaddrinfo() function. This function is configured in various ways by the /etc/resolv.conf file, which tells glibc what nameserver/resolver to contact as well as how to talk to the name server. By default, glibc performs UDP DNS queries, with a single DNS query per UDP packet. The UDP packet size is limited per DNS spec to 512 bytes. For some DNS lookups, a 512 byte UDP packet is not large enough to contain the entire response - for example, an A record lookup with a large number (e.g. 30) of A record addresses. This number of A record entries is possible in some cases of load balancing. When the DNS UDP response size is larger than 512 bytes, the server puts as much response as it can into the DNS UDP response, and marks the "trunacted" flag. This lets glibc know that the DNS UDP packet did not contain the entire response for all the A records. When glibc sees a UDP response that is "trunacted", by default it ignores the contents of that response and issues a new DNS query, using TCP instead of UDP. The TCP packet size has a higher size limit (though see bug 1804487 which is a bug in systemd's max-sizing of TCP DNS packets), and so *should* allow glibc to receive the entire DNS response. However, glibc issues DNS queries for both A and records. When it uses UDP, those DNS queries are separate (i.e. one UDP DNS packet with a single A query, and one UDP DNS packet with a single query). When glibc uses TCP, it puts both DNS queries into a single TCP DNS packet - the RFC refers to this as "pipelining" (https://tools.ietf.org/html/rfc7766#section-6.2.1.1) and states that clients SHOULD do this, and that servers MUST expect to receive pipelined queries and SHOULD respond to all of them. (Technically pipelining can be separate DNS queries, one per TCP packet, but both using the same TCP connection - but the clear intention of pipelining is to improve TCP performance, and putting both DNS queries into a single TCP packet is clearly more performant than using separate TCP packets). Unfortunately, systemd's local stub resolver has only very basic support for TCP DNS, and it handles TCP DNS queries almost identically to UDP DNS queries - it reads the DNS query 2-byte header (containing the length of the query data), reads in the single DNS query data, performs lookup and sends a response to that DNS query, and closes the TCP connection. It does not check for "pipelined" queries in the TCP connection. That would be bad enough, as glibc is (rightly) expecting a response to both its A and queries; however what glibc gets is a TCP connection-reset error. That is because the local systemd stub resolver has closed its TCP socket while input data was still pending (i.e. it never even read the second pipelined DNS query). When the kernel sees unread input bytes in a TCP connection that is closed, it sends a TCP RST to the peer (i.e. glibc) and when the kernel sees the RST, it dumps all data in its socket buffer and passes the ECONNRESET error up to the application. So glibc gets nothing besides a connection reset error. Note also that even if the systemd local stub resolver's socket flushes its input buffer before closing the TCP connection (which will avoid the TCP RST), glibc still expects responses to both its A and queries before systemd closes the TCP connection, and so a simple
[Group.of.nepali.translators] [Bug 1811471] Re: local resolver stub fails to handle multiple TCP dns queries
This bug was fixed in the package systemd - 240-5ubuntu3 --- systemd (240-5ubuntu3) disco; urgency=medium * debian/tests: blacklist upstream test-24-unit-tests on ppc64le. Fails, not a regression as it's a new test case, which was never before executed on ppc64le. File: debian/tests/upstream https://git.launchpad.net/~ubuntu-core-dev/ubuntu/+source/systemd/commit/?id=8062b9a2712c390010d2948eaf764a1b52e68715 -- Dimitri John Ledkov Sat, 02 Feb 2019 11:05:12 +0100 ** Changed in: systemd (Ubuntu Disco) Status: Fix Committed => Fix Released -- You received this bug notification because you are a member of नेपाली भाषा समायोजकहरुको समूह, which is subscribed to Xenial. Matching subscriptions: Ubuntu 16.04 Bugs https://bugs.launchpad.net/bugs/1811471 Title: local resolver stub fails to handle multiple TCP dns queries Status in systemd: New Status in systemd package in Ubuntu: Fix Released Status in systemd source package in Trusty: Invalid Status in systemd source package in Xenial: Invalid Status in systemd source package in Bionic: Fix Committed Status in systemd source package in Cosmic: Fix Committed Status in systemd source package in Disco: Fix Released Bug description: [Impact] The systemd local 'stub' resolver handles all local DNS queries (by default configuration used in Ubuntu), and essentially proxies all requests to its configured upstream DNS resolvers. Most local DNS resolution by applications uses glibc's getaddrinfo() function. This function is configured in various ways by the /etc/resolv.conf file, which tells glibc what nameserver/resolver to contact as well as how to talk to the name server. By default, glibc performs UDP DNS queries, with a single DNS query per UDP packet. The UDP packet size is limited per DNS spec to 512 bytes. For some DNS lookups, a 512 byte UDP packet is not large enough to contain the entire response - for example, an A record lookup with a large number (e.g. 30) of A record addresses. This number of A record entries is possible in some cases of load balancing. When the DNS UDP response size is larger than 512 bytes, the server puts as much response as it can into the DNS UDP response, and marks the "trunacted" flag. This lets glibc know that the DNS UDP packet did not contain the entire response for all the A records. When glibc sees a UDP response that is "trunacted", by default it ignores the contents of that response and issues a new DNS query, using TCP instead of UDP. The TCP packet size has a higher size limit (though see bug 1804487 which is a bug in systemd's max-sizing of TCP DNS packets), and so *should* allow glibc to receive the entire DNS response. However, glibc issues DNS queries for both A and records. When it uses UDP, those DNS queries are separate (i.e. one UDP DNS packet with a single A query, and one UDP DNS packet with a single query). When glibc uses TCP, it puts both DNS queries into a single TCP DNS packet - the RFC refers to this as "pipelining" (https://tools.ietf.org/html/rfc7766#section-6.2.1.1) and states that clients SHOULD do this, and that servers MUST expect to receive pipelined queries and SHOULD respond to all of them. (Technically pipelining can be separate DNS queries, one per TCP packet, but both using the same TCP connection - but the clear intention of pipelining is to improve TCP performance, and putting both DNS queries into a single TCP packet is clearly more performant than using separate TCP packets). Unfortunately, systemd's local stub resolver has only very basic support for TCP DNS, and it handles TCP DNS queries almost identically to UDP DNS queries - it reads the DNS query 2-byte header (containing the length of the query data), reads in the single DNS query data, performs lookup and sends a response to that DNS query, and closes the TCP connection. It does not check for "pipelined" queries in the TCP connection. That would be bad enough, as glibc is (rightly) expecting a response to both its A and queries; however what glibc gets is a TCP connection-reset error. That is because the local systemd stub resolver has closed its TCP socket while input data was still pending (i.e. it never even read the second pipelined DNS query). When the kernel sees unread input bytes in a TCP connection that is closed, it sends a TCP RST to the peer (i.e. glibc) and when the kernel sees the RST, it dumps all data in its socket buffer and passes the ECONNRESET error up to the application. So glibc gets nothing besides a connection reset error. Note also that even if the systemd local stub resolver's socket flushes its input buffer before closing the TCP connection (which will avoid the TCP RST), glibc still expects responses to both its A and queries before systemd closes the TCP connection, and so a simple change
[Group.of.nepali.translators] [Bug 1811471] Re: local resolver stub fails to handle multiple TCP dns queries
** Changed in: systemd (Ubuntu Xenial) Status: In Progress => Invalid ** Changed in: systemd (Ubuntu Trusty) Status: In Progress => Invalid ** Changed in: systemd (Ubuntu Xenial) Importance: High => Undecided ** Changed in: systemd (Ubuntu Trusty) Importance: High => Undecided ** Changed in: systemd (Ubuntu Trusty) Assignee: Dan Streetman (ddstreet) => (unassigned) ** Changed in: systemd (Ubuntu Xenial) Assignee: Dan Streetman (ddstreet) => (unassigned) ** Description changed: [Impact] The systemd local 'stub' resolver handles all local DNS queries (by default configuration used in Ubuntu), and essentially proxies all requests to its configured upstream DNS resolvers. Most local DNS resolution by applications uses glibc's getaddrinfo() function. This function is configured in various ways by the /etc/resolv.conf file, which tells glibc what nameserver/resolver to contact as well as how to talk to the name server. By default, glibc performs UDP DNS queries, with a single DNS query per UDP packet. The UDP packet size is limited per DNS spec to 512 bytes. For some DNS lookups, a 512 byte UDP packet is not large enough to contain the entire response - for example, an A record lookup with a large number (e.g. 30) of A record addresses. This number of A record entries is possible in some cases of load balancing. When the DNS UDP response size is larger than 512 bytes, the server puts as much response as it can into the DNS UDP response, and marks the "trunacted" flag. This lets glibc know that the DNS UDP packet did not contain the entire response for all the A records. When glibc sees a UDP response that is "trunacted", by default it ignores the contents of that response and issues a new DNS query, using TCP instead of UDP. The TCP packet size has a higher size limit (though see bug 1804487 which is a bug in systemd's max-sizing of TCP DNS packets), and so *should* allow glibc to receive the entire DNS response. However, glibc issues DNS queries for both A and records. When it uses UDP, those DNS queries are separate (i.e. one UDP DNS packet with a single A query, and one UDP DNS packet with a single query). When glibc uses TCP, it puts both DNS queries into a single TCP DNS packet - the RFC refers to this as "pipelining" (https://tools.ietf.org/html/rfc7766#section-6.2.1.1) and states that clients SHOULD do this, and that servers MUST expect to receive pipelined queries and SHOULD respond to all of them. (Technically pipelining can be separate DNS queries, one per TCP packet, but both using the same TCP connection - but the clear intention of pipelining is to improve TCP performance, and putting both DNS queries into a single TCP packet is clearly more performant than using separate TCP packets). Unfortunately, systemd's local stub resolver has only very basic support for TCP DNS, and it handles TCP DNS queries almost identically to UDP DNS queries - it reads the DNS query 2-byte header (containing the length of the query data), reads in the single DNS query data, performs lookup and sends a response to that DNS query, and closes the TCP connection. It does not check for "pipelined" queries in the TCP connection. That would be bad enough, as glibc is (rightly) expecting a response to both its A and queries; however what glibc gets is a TCP connection-reset error. That is because the local systemd stub resolver has closed its TCP socket while input data was still pending (i.e. it never even read the second pipelined DNS query). When the kernel sees unread input bytes in a TCP connection that is closed, it sends a TCP RST to the peer (i.e. glibc) and when the kernel sees the RST, it dumps all data in its socket buffer and passes the ECONNRESET error up to the application. So glibc gets nothing besides a connection reset error. Note also that even if the systemd local stub resolver's socket flushes its input buffer before closing the TCP connection (which will avoid the TCP RST), glibc still expects responses to both its A and queries before systemd closes the TCP connection, and so a simple change to systemd to flush the input buffer is not enough to fix the bug (and would also not actually fix the bug since glibc would never get the response). [Test Case] This can be reproduced on any system using a local systemd stub resolver, when using an application that uses getaddrinfo() - such as ssh, telnet, ping, etc - or with a simple C program that uses getaddrinfo(). The dns name looked up must have enough A records to overflow the 512 byte maximum for a UDP DNS packet. Alternately, and trivially, glibc can be forced to always use TCP DNS queries by editing the /etc/resolv.conf file and adding: options use-vc With that option, glibc will fail to lookup 100% of DNS names,
[Group.of.nepali.translators] [Bug 1811471] Re: local resolver stub fails to handle multiple TCP dns queries
** Bug watch added: github.com/systemd/systemd/issues #11332 https://github.com/systemd/systemd/issues/11332 ** Also affects: systemd via https://github.com/systemd/systemd/issues/11332 Importance: Unknown Status: Unknown -- You received this bug notification because you are a member of नेपाली भाषा समायोजकहरुको समूह, which is subscribed to Xenial. Matching subscriptions: Ubuntu 16.04 Bugs https://bugs.launchpad.net/bugs/1811471 Title: local resolver stub fails to handle multiple TCP dns queries Status in systemd: Unknown Status in systemd package in Ubuntu: In Progress Status in systemd source package in Trusty: In Progress Status in systemd source package in Xenial: In Progress Status in systemd source package in Bionic: In Progress Status in systemd source package in Cosmic: In Progress Status in systemd source package in Disco: In Progress Bug description: [Impact] The systemd local 'stub' resolver handles all local DNS queries (by default configuration used in Ubuntu), and essentially proxies all requests to its configured upstream DNS resolvers. Most local DNS resolution by applications uses glibc's getaddrinfo() function. This function is configured in various ways by the /etc/resolv.conf file, which tells glibc what nameserver/resolver to contact as well as how to talk to the name server. By default, glibc performs UDP DNS queries, with a single DNS query per UDP packet. The UDP packet size is limited per DNS spec to 512 bytes. For some DNS lookups, a 512 byte UDP packet is not large enough to contain the entire response - for example, an A record lookup with a large number (e.g. 30) of A record addresses. This number of A record entries is possible in some cases of load balancing. When the DNS UDP response size is larger than 512 bytes, the server puts as much response as it can into the DNS UDP response, and marks the "trunacted" flag. This lets glibc know that the DNS UDP packet did not contain the entire response for all the A records. When glibc sees a UDP response that is "trunacted", by default it ignores the contents of that response and issues a new DNS query, using TCP instead of UDP. The TCP packet size has a higher size limit (though see bug 1804487 which is a bug in systemd's max-sizing of TCP DNS packets), and so *should* allow glibc to receive the entire DNS response. However, glibc issues DNS queries for both A and records. When it uses UDP, those DNS queries are separate (i.e. one UDP DNS packet with a single A query, and one UDP DNS packet with a single query). When glibc uses TCP, it puts both DNS queries into a single TCP DNS packet - the RFC refers to this as "pipelining" (https://tools.ietf.org/html/rfc7766#section-6.2.1.1) and states that clients SHOULD do this, and that servers MUST expect to receive pipelined queries and SHOULD respond to all of them. (Technically pipelining can be separate DNS queries, one per TCP packet, but both using the same TCP connection - but the clear intention of pipelining is to improve TCP performance, and putting both DNS queries into a single TCP packet is clearly more performant than using separate TCP packets). Unfortunately, systemd's local stub resolver has only very basic support for TCP DNS, and it handles TCP DNS queries almost identically to UDP DNS queries - it reads the DNS query 2-byte header (containing the length of the query data), reads in the single DNS query data, performs lookup and sends a response to that DNS query, and closes the TCP connection. It does not check for "pipelined" queries in the TCP connection. That would be bad enough, as glibc is (rightly) expecting a response to both its A and queries; however what glibc gets is a TCP connection-reset error. That is because the local systemd stub resolver has closed its TCP socket while input data was still pending (i.e. it never even read the second pipelined DNS query). When the kernel sees unread input bytes in a TCP connection that is closed, it sends a TCP RST to the peer (i.e. glibc) and when the kernel sees the RST, it dumps all data in its socket buffer and passes the ECONNRESET error up to the application. So glibc gets nothing besides a connection reset error. Note also that even if the systemd local stub resolver's socket flushes its input buffer before closing the TCP connection (which will avoid the TCP RST), glibc still expects responses to both its A and queries before systemd closes the TCP connection, and so a simple change to systemd to flush the input buffer is not enough to fix the bug (and would also not actually fix the bug since glibc would never get the response). [Test Case] This can be reproduced on any system using a local systemd stub resolver, when using an application that uses getaddrinfo() - such as ssh, telnet, ping, etc - or