Cap WHOIS answers and follow referrals only to WHOIS servers (closes #106)
check / check (push) Canceled after 0s
check / check (push) Canceled after 0s
The client kept every line a WHOIS server sent until the server closed the connection or 30 seconds passed, so a server that kept sending could fill memory. It now reads at most 1 MiB of an answer, and an answer that reaches that is an error. A "refer:" line in IANA's answer naming a server none of the five RIRs run was dialled as given, on any host and port; it is now an error, so the client only connects to IANA and the five RIR servers. Both errors are failed lookups, which the fetcher retries later. Model: opus-5-5
This commit is contained in:
@@ -6,6 +6,7 @@ import (
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"testing"
|
||||
@@ -71,6 +72,13 @@ const ianaNoObject = `% IANA WHOIS server
|
||||
% This query returned 0 objects.
|
||||
`
|
||||
|
||||
// fillerLine is one of the lines a server that does not stop keeps sending.
|
||||
const fillerLine = "remarks: and more\n"
|
||||
|
||||
// endlessAnswerSize is how many bytes of filler lines that server sends:
|
||||
// four times the client's cap on an answer.
|
||||
const endlessAnswerSize = 4 << 20
|
||||
|
||||
// fakeServers returns a DialContext for a whois.Client that connects to a
|
||||
// fake server for each address in answers, which reads the query and sends
|
||||
// answers[address]. Connecting to any other address is refused.
|
||||
@@ -187,3 +195,52 @@ func TestLookupASNFailsWhenIANAAnswersNoBlock(t *testing.T) {
|
||||
err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestLookupASNFailsWhenTheRIRAnswerDoesNotEnd looks up an AS whose RIR
|
||||
// server follows the record with filler lines far past any real answer.
|
||||
// The client stops reading at its cap and fails instead of keeping them.
|
||||
func TestLookupASNFailsWhenTheRIRAnswerDoesNotEnd(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
endless := ripeRecord +
|
||||
strings.Repeat(fillerLine, endlessAnswerSize/len(fillerLine))
|
||||
|
||||
_, err := lookUp(t, map[string]string{
|
||||
ianaServer: ianaReferral,
|
||||
ripeServer: endless,
|
||||
})
|
||||
if err == nil || errors.Is(err, whois.ErrNoReferral) {
|
||||
t.Errorf("LookupASN error = %v, want one that is not ErrNoReferral",
|
||||
err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestLookupASNFailsOnAReferralToAnotherServer looks up an AS when IANA's
|
||||
// answer refers it to a server none of the five RIRs run, with a port and
|
||||
// without. The client follows a referral only to an RIR's server, so it
|
||||
// fails instead of asking that server, which would answer with a record.
|
||||
func TestLookupASNFailsOnAReferralToAnotherServer(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Each case maps the server on the "refer:" line to the address the
|
||||
// client would dial to follow it. IANA's answer also names the AS's
|
||||
// block, so a client that dropped the referral would report no RIR.
|
||||
for refer, address := range map[string]string{
|
||||
"whois.example.net:8080": "whois.example.net:8080",
|
||||
"whois.example.net": "whois.example.net:43",
|
||||
} {
|
||||
t.Run(refer, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, err := lookUp(t, map[string]string{
|
||||
ianaServer: "refer: " + refer + "\n\n" +
|
||||
"as-block: 3154-3353\n",
|
||||
address: ripeRecord,
|
||||
})
|
||||
if err == nil || errors.Is(err, whois.ErrNoReferral) {
|
||||
t.Errorf("LookupASN error = %v, want one that is not "+
|
||||
"ErrNoReferral", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user