Skip to content

Commit

Permalink
fix(webconnectivitylte): handle site with no IP addrs
Browse files Browse the repository at this point in the history
This diff improves webconnectivitylte and minipipeline to correctly
handle the case where a website has no configured IP addresses but
the domain for the website exists.

Let's also add QA test cases to make sure we don't regress.

Part of ooni/probe#2652.
  • Loading branch information
bassosimone committed Jan 24, 2024
1 parent 2cc9231 commit b854219
Show file tree
Hide file tree
Showing 9 changed files with 1,010 additions and 4 deletions.
12 changes: 9 additions & 3 deletions internal/experiment/webconnectivitylte/analysisclassic.go
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,15 @@ func analysisClassicComputeBlockingAccessible(woa *minipipeline.WebAnalysis, tk
return
}

// 5.3. special case for when the probe failed with dns_no_data and the
// test helper returned no addresses, which is its way to tell us the same
// error occurred but we need to interpret it as dns_no_data.
if !entry.ControlDNSResolvedAddrs.IsNone() &&
entry.ControlDNSResolvedAddrs.Unwrap().Len() <= 0 {
tk.setWebsiteDown()
return
}

// 5.3. Handle the case where just the probe failed.
tk.setBlockingString("dns")
tk.setHTTPExperimentFailure(entry.Failure)
Expand Down Expand Up @@ -406,9 +415,6 @@ func analysisClassicComputeBlockingAccessible(woa *minipipeline.WebAnalysis, tk
tk.setWebsiteDown()
return
}

// TODO(bassosimone): we should handle the case where a domain
// exists but there aren't IP addresses for it.
}
}

Expand Down
1 change: 1 addition & 0 deletions internal/experiment/webconnectivityqa/testcase.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ func AllTestCases() []*TestCase {
tlsBlockingConnectionResetWithInconsistentDNS(),

websiteDownNXDOMAIN(),
websiteDownNoAddrs(),
websiteDownTCPConnect(),
}
}
28 changes: 28 additions & 0 deletions internal/experiment/webconnectivityqa/websitedown.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package webconnectivityqa

import "github.com/ooni/probe-cli/v3/internal/netemx"

// websiteDownNXDOMAIN describes the test case where the website domain
// is NXDOMAIN according to the TH and the probe.
func websiteDownNXDOMAIN() *TestCase {
Expand Down Expand Up @@ -60,3 +62,29 @@ func websiteDownTCPConnect() *TestCase {
},
}
}

// websiteDownNoAddrs describes the test case where the website domain
// does not return any address according to the TH and the probe.
func websiteDownNoAddrs() *TestCase {
return &TestCase{
Name: "websiteDownNoAddrs",
Flags: TestCaseFlagNoV04,
Input: "http://www.example.com/", // domain not defined in the simulation
Configure: func(env *netemx.QAEnv) {

// reconfigure with only CNAME but no addresses and do this
// for all the resolvers of the kingdom
env.AddRecordToAllResolvers("www.example.com", "web01.example.com" /* No addrs */)

},
ExpectErr: false,
ExpectTestKeys: &testKeys{
DNSExperimentFailure: "dns_no_answer",
DNSConsistency: "consistent",
XBlockingFlags: 0,
XNullNullFlags: 1, // AnalysisFlagNullNullExpectedDNSLookupFailure
Accessible: false,
Blocking: false,
},
}
}
9 changes: 8 additions & 1 deletion internal/minipipeline/analysis.go
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,14 @@ func (wa *WebAnalysis) dnsComputeFailureMetrics(c *WebObservationsContainer) {
}

// handle the case where only the probe failed
if obs.DNSLookupFailure.Unwrap() != "" {
if failure := obs.DNSLookupFailure.Unwrap(); failure != "" {
// When the probe says dns_no_answer the control would otherwise say that
// we have resolved zero IP addresses for historical reasons. In such a case,
// let's pretend also the control returned dns_no_answer.
if !obs.ControlDNSResolvedAddrs.IsNone() && obs.ControlDNSResolvedAddrs.Unwrap().Len() <= 0 {
wa.DNSLookupExpectedFailure.Add(obs.DNSTransactionID.Unwrap())
continue
}
wa.DNSLookupUnexpectedFailure.Add(obs.DNSTransactionID.Unwrap())
continue
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,261 @@
{
"ControlExpectations": {
"DNSAddresses": [],
"FinalResponseFailure": "dns_lookup_error"
},
"DNSLookupSuccess": [],
"DNSLookupSuccessWithInvalidAddresses": [],
"DNSLookupSuccessWithValidAddress": [],
"DNSLookupSuccessWithBogonAddresses": [],
"DNSLookupSuccessWithInvalidAddressesClassic": [],
"DNSLookupSuccessWithValidAddressClassic": [],
"DNSLookupUnexpectedFailure": [],
"DNSLookupUnexplainedFailure": [],
"DNSExperimentFailure": "dns_no_answer",
"DNSLookupExpectedFailure": [
2,
3
],
"DNSLookupExpectedSuccess": [],
"TCPConnectExpectedFailure": [],
"TCPConnectUnexpectedFailure": [],
"TCPConnectUnexpectedFailureDuringWebFetch": [],
"TCPConnectUnexpectedFailureDuringConnectivityCheck": [],
"TCPConnectUnexplainedFailure": [],
"TCPConnectUnexplainedFailureDuringWebFetch": [],
"TCPConnectUnexplainedFailureDuringConnectivityCheck": [],
"TLSHandshakeExpectedFailure": [],
"TLSHandshakeUnexpectedFailure": [],
"TLSHandshakeUnexpectedFailureDuringWebFetch": [],
"TLSHandshakeUnexpectedFailureDuringConnectivityCheck": [],
"TLSHandshakeUnexplainedFailure": [],
"TLSHandshakeUnexplainedFailureDuringWebFetch": [],
"TLSHandshakeUnexplainedFailureDuringConnectivityCheck": [],
"HTTPRoundTripUnexpectedFailure": [],
"HTTPRoundTripUnexplainedFailure": [],
"HTTPFinalResponseSuccessTLSWithoutControl": null,
"HTTPFinalResponseSuccessTLSWithControl": null,
"HTTPFinalResponseSuccessTCPWithoutControl": null,
"HTTPFinalResponseSuccessTCPWithControl": null,
"HTTPFinalResponseDiffBodyProportionFactor": null,
"HTTPFinalResponseDiffStatusCodeMatch": null,
"HTTPFinalResponseDiffTitleDifferentLongWords": null,
"HTTPFinalResponseDiffUncommonHeadersIntersection": null,
"Linear": [
{
"TagDepth": 0,
"Type": 0,
"Failure": "dns_no_answer",
"TransactionID": 3,
"TagFetchBody": null,
"DNSTransactionID": 3,
"DNSDomain": "www.example.com",
"DNSLookupFailure": "dns_no_answer",
"DNSQueryType": "A",
"DNSEngine": "udp",
"DNSResolvedAddrs": null,
"IPAddressOrigin": null,
"IPAddress": null,
"IPAddressASN": null,
"IPAddressBogon": null,
"EndpointTransactionID": null,
"EndpointProto": null,
"EndpointPort": null,
"EndpointAddress": null,
"TCPConnectFailure": null,
"TLSHandshakeFailure": null,
"TLSServerName": null,
"HTTPRequestURL": null,
"HTTPFailure": null,
"HTTPResponseStatusCode": null,
"HTTPResponseBodyLength": null,
"HTTPResponseBodyIsTruncated": null,
"HTTPResponseHeadersKeys": null,
"HTTPResponseLocation": null,
"HTTPResponseTitle": null,
"HTTPResponseIsFinal": null,
"ControlDNSDomain": "www.example.com",
"ControlDNSLookupFailure": "",
"ControlDNSResolvedAddrs": [],
"ControlTCPConnectFailure": null,
"ControlTLSHandshakeFailure": null,
"ControlHTTPFailure": "dns_lookup_error",
"ControlHTTPResponseStatusCode": null,
"ControlHTTPResponseBodyLength": null,
"ControlHTTPResponseHeadersKeys": null,
"ControlHTTPResponseTitle": null
},
{
"TagDepth": 0,
"Type": 0,
"Failure": "dns_no_answer",
"TransactionID": 3,
"TagFetchBody": null,
"DNSTransactionID": 3,
"DNSDomain": "www.example.com",
"DNSLookupFailure": "dns_no_answer",
"DNSQueryType": "AAAA",
"DNSEngine": "udp",
"DNSResolvedAddrs": null,
"IPAddressOrigin": null,
"IPAddress": null,
"IPAddressASN": null,
"IPAddressBogon": null,
"EndpointTransactionID": null,
"EndpointProto": null,
"EndpointPort": null,
"EndpointAddress": null,
"TCPConnectFailure": null,
"TLSHandshakeFailure": null,
"TLSServerName": null,
"HTTPRequestURL": null,
"HTTPFailure": null,
"HTTPResponseStatusCode": null,
"HTTPResponseBodyLength": null,
"HTTPResponseBodyIsTruncated": null,
"HTTPResponseHeadersKeys": null,
"HTTPResponseLocation": null,
"HTTPResponseTitle": null,
"HTTPResponseIsFinal": null,
"ControlDNSDomain": "www.example.com",
"ControlDNSLookupFailure": "",
"ControlDNSResolvedAddrs": [],
"ControlTCPConnectFailure": null,
"ControlTLSHandshakeFailure": null,
"ControlHTTPFailure": "dns_lookup_error",
"ControlHTTPResponseStatusCode": null,
"ControlHTTPResponseBodyLength": null,
"ControlHTTPResponseHeadersKeys": null,
"ControlHTTPResponseTitle": null
},
{
"TagDepth": 0,
"Type": 0,
"Failure": "dns_no_answer",
"TransactionID": 2,
"TagFetchBody": null,
"DNSTransactionID": 2,
"DNSDomain": "www.example.com",
"DNSLookupFailure": "dns_no_answer",
"DNSQueryType": "ANY",
"DNSEngine": "getaddrinfo",
"DNSResolvedAddrs": null,
"IPAddressOrigin": null,
"IPAddress": null,
"IPAddressASN": null,
"IPAddressBogon": null,
"EndpointTransactionID": null,
"EndpointProto": null,
"EndpointPort": null,
"EndpointAddress": null,
"TCPConnectFailure": null,
"TLSHandshakeFailure": null,
"TLSServerName": null,
"HTTPRequestURL": null,
"HTTPFailure": null,
"HTTPResponseStatusCode": null,
"HTTPResponseBodyLength": null,
"HTTPResponseBodyIsTruncated": null,
"HTTPResponseHeadersKeys": null,
"HTTPResponseLocation": null,
"HTTPResponseTitle": null,
"HTTPResponseIsFinal": null,
"ControlDNSDomain": "www.example.com",
"ControlDNSLookupFailure": "",
"ControlDNSResolvedAddrs": [],
"ControlTCPConnectFailure": null,
"ControlTLSHandshakeFailure": null,
"ControlHTTPFailure": "dns_lookup_error",
"ControlHTTPResponseStatusCode": null,
"ControlHTTPResponseBodyLength": null,
"ControlHTTPResponseHeadersKeys": null,
"ControlHTTPResponseTitle": null
},
{
"TagDepth": 0,
"Type": 0,
"Failure": "dns_nxdomain_error",
"TransactionID": 1,
"TagFetchBody": null,
"DNSTransactionID": 1,
"DNSDomain": "www.example.com",
"DNSLookupFailure": "dns_nxdomain_error",
"DNSQueryType": "AAAA",
"DNSEngine": "doh",
"DNSResolvedAddrs": null,
"IPAddressOrigin": null,
"IPAddress": null,
"IPAddressASN": null,
"IPAddressBogon": null,
"EndpointTransactionID": null,
"EndpointProto": null,
"EndpointPort": null,
"EndpointAddress": null,
"TCPConnectFailure": null,
"TLSHandshakeFailure": null,
"TLSServerName": null,
"HTTPRequestURL": null,
"HTTPFailure": null,
"HTTPResponseStatusCode": null,
"HTTPResponseBodyLength": null,
"HTTPResponseBodyIsTruncated": null,
"HTTPResponseHeadersKeys": null,
"HTTPResponseLocation": null,
"HTTPResponseTitle": null,
"HTTPResponseIsFinal": null,
"ControlDNSDomain": "www.example.com",
"ControlDNSLookupFailure": "",
"ControlDNSResolvedAddrs": [],
"ControlTCPConnectFailure": null,
"ControlTLSHandshakeFailure": null,
"ControlHTTPFailure": "dns_lookup_error",
"ControlHTTPResponseStatusCode": null,
"ControlHTTPResponseBodyLength": null,
"ControlHTTPResponseHeadersKeys": null,
"ControlHTTPResponseTitle": null
},
{
"TagDepth": 0,
"Type": 0,
"Failure": "dns_nxdomain_error",
"TransactionID": 1,
"TagFetchBody": null,
"DNSTransactionID": 1,
"DNSDomain": "www.example.com",
"DNSLookupFailure": "dns_nxdomain_error",
"DNSQueryType": "A",
"DNSEngine": "doh",
"DNSResolvedAddrs": null,
"IPAddressOrigin": null,
"IPAddress": null,
"IPAddressASN": null,
"IPAddressBogon": null,
"EndpointTransactionID": null,
"EndpointProto": null,
"EndpointPort": null,
"EndpointAddress": null,
"TCPConnectFailure": null,
"TLSHandshakeFailure": null,
"TLSServerName": null,
"HTTPRequestURL": null,
"HTTPFailure": null,
"HTTPResponseStatusCode": null,
"HTTPResponseBodyLength": null,
"HTTPResponseBodyIsTruncated": null,
"HTTPResponseHeadersKeys": null,
"HTTPResponseLocation": null,
"HTTPResponseTitle": null,
"HTTPResponseIsFinal": null,
"ControlDNSDomain": "www.example.com",
"ControlDNSLookupFailure": "",
"ControlDNSResolvedAddrs": [],
"ControlTCPConnectFailure": null,
"ControlTLSHandshakeFailure": null,
"ControlHTTPFailure": "dns_lookup_error",
"ControlHTTPResponseStatusCode": null,
"ControlHTTPResponseBodyLength": null,
"ControlHTTPResponseHeadersKeys": null,
"ControlHTTPResponseTitle": null
}
]
}
Loading

0 comments on commit b854219

Please sign in to comment.