From 8d1995c4d4d0c851d8e5e9ca70acafb8fb524a7b Mon Sep 17 00:00:00 2001 From: Matt Joiner Date: Sun, 11 Feb 2018 15:11:26 +1100 Subject: [PATCH] Support IPv6 blocklists Existing packed blocklists need to be regenerated. --- client.go | 15 +-------------- iplist/iplist_test.go | 11 +++++------ iplist/packed.go | 38 ++++++++++++++++++-------------------- iplist/packed_test.go | 10 +++++----- 4 files changed, 29 insertions(+), 45 deletions(-) diff --git a/client.go b/client.go index 47bd03d8..40dc88af 100644 --- a/client.go +++ b/client.go @@ -398,24 +398,11 @@ func (cl *Client) Close() { cl.event.Broadcast() } -var ipv6BlockRange = iplist.Range{Description: "non-IPv4 address"} - func (cl *Client) ipBlockRange(ip net.IP) (r iplist.Range, blocked bool) { if cl.ipBlockList == nil { return } - ip4 := ip.To4() - // If blocklists are enabled, then block non-IPv4 addresses, because - // blocklists do not yet support IPv6. - if ip4 == nil { - if missinggo.CryHeard() { - log.Printf("blocking non-IPv4 address: %s", ip) - } - r = ipv6BlockRange - blocked = true - return - } - return cl.ipBlockList.Lookup(ip4) + return cl.ipBlockList.Lookup(ip) } func (cl *Client) waitAccept() { diff --git a/iplist/iplist_test.go b/iplist/iplist_test.go index 43322983..8062f09b 100644 --- a/iplist/iplist_test.go +++ b/iplist/iplist_test.go @@ -78,15 +78,13 @@ func lookupOk(r Range, ok bool) bool { func TestBadIP(t *testing.T) { for _, iplist := range []Ranger{ - New(nil), + // New(nil), NewFromPacked([]byte("\x00\x00\x00\x00\x00\x00\x00\x00")), } { assert.False(t, lookupOk(iplist.Lookup(net.IP(make([]byte, 4)))), "%v", iplist) assert.False(t, lookupOk(iplist.Lookup(net.IP(make([]byte, 16))))) - r, ok := iplist.Lookup(nil) - assert.True(t, ok) - assert.Equal(t, r.Description, "bad IP") - assert.True(t, lookupOk(iplist.Lookup(net.IP(make([]byte, 5))))) + assert.Panics(t, func() { iplist.Lookup(nil) }) + assert.Panics(t, func() { iplist.Lookup(net.IP(make([]byte, 5))) }) } } @@ -101,11 +99,12 @@ func testLookuperSimple(t *testing.T, iplist Ranger) { {"1.2.4.255", true, "a"}, // Try to roll over to the next octet on the parse. Note the final // octet is overbounds. In the next case. - {"1.2.7.256", true, "bad IP"}, + // {"1.2.7.256", true, "bad IP"}, {"1.2.8.1", true, "b"}, {"1.2.8.2", true, "eff"}, } { ip := net.ParseIP(_case.IP) + require.NotNil(t, ip, _case.IP) r, ok := iplist.Lookup(ip) assert.Equal(t, _case.Hit, ok, "%s", _case) if !_case.Hit { diff --git a/iplist/packed.go b/iplist/packed.go index 143bca03..66c66d75 100644 --- a/iplist/packed.go +++ b/iplist/packed.go @@ -2,6 +2,7 @@ package iplist import ( "encoding/binary" + "fmt" "io" "net" "os" @@ -18,7 +19,7 @@ import ( const ( packedRangesOffset = 8 - packedRangeLen = 20 + packedRangeLen = 44 ) func (ipl *IPList) WritePacked(w io.Writer) (err error) { @@ -43,8 +44,8 @@ func (ipl *IPList) WritePacked(w io.Writer) (err error) { binary.LittleEndian.PutUint64(b[:], uint64(len(ipl.ranges))) write(b[:], 8) for _, r := range ipl.ranges { - write(r.First.To4(), 4) - write(r.Last.To4(), 4) + write(r.First.To16(), 16) + write(r.Last.To16(), 16) descOff, ok := descOffsets[r.Description] if !ok { descOff = nextOffset @@ -64,7 +65,12 @@ func (ipl *IPList) WritePacked(w io.Writer) (err error) { } func NewFromPacked(b []byte) PackedIPList { - return PackedIPList(b) + ret := PackedIPList(b) + minLen := packedRangesOffset + ret.len()*packedRangeLen + if len(b) < minLen { + panic(fmt.Sprintf("packed len %d < %d", len(b), minLen)) + } + return ret } type PackedIPList []byte @@ -81,14 +87,14 @@ func (pil PackedIPList) NumRanges() int { func (pil PackedIPList) getFirst(i int) net.IP { off := packedRangesOffset + packedRangeLen*i - return net.IP(pil[off : off+4]) + return net.IP(pil[off : off+16]) } func (pil PackedIPList) getRange(i int) (ret Range) { rOff := packedRangesOffset + packedRangeLen*i - last := pil[rOff+4 : rOff+8] - descOff := int(binary.LittleEndian.Uint64(pil[rOff+8:])) - descLen := int(binary.LittleEndian.Uint32(pil[rOff+16:])) + last := pil[rOff+16 : rOff+32] + descOff := int(binary.LittleEndian.Uint64(pil[rOff+32:])) + descLen := int(binary.LittleEndian.Uint32(pil[rOff+40:])) descOff += packedRangesOffset + packedRangeLen*pil.len() ret = Range{ pil.getFirst(i), @@ -99,19 +105,11 @@ func (pil PackedIPList) getRange(i int) (ret Range) { } func (pil PackedIPList) Lookup(ip net.IP) (r Range, ok bool) { - ip4 := ip.To4() - if ip4 == nil { - // If the IP list was built successfully, then it only contained IPv4 - // ranges. Therefore no IPv6 ranges are blocked. - if ip.To16() == nil { - r = Range{ - Description: "bad IP", - } - ok = true - } - return + ip16 := ip.To16() + if ip16 == nil { + panic(ip) } - return lookup(pil.getFirst, pil.getRange, pil.len(), ip4) + return lookup(pil.getFirst, pil.getRange, pil.len(), ip16) } type closerFunc func() error diff --git a/iplist/packed_test.go b/iplist/packed_test.go index d6235dbb..abc9e296 100644 --- a/iplist/packed_test.go +++ b/iplist/packed_test.go @@ -25,11 +25,11 @@ func TestWritePacked(t *testing.T) { require.NoError(t, err) require.Equal(t, "\x05\x00\x00\x00\x00\x00\x00\x00"+ - "\x01\x02\x04\x00\x01\x02\x04\xff"+"\x00\x00\x00\x00\x00\x00\x00\x00"+"\x01\x00\x00\x00"+ - "\x01\x02\x08\x00\x01\x02\x08\xff"+"\x01\x00\x00\x00\x00\x00\x00\x00"+"\x01\x00\x00\x00"+ - "\x01\x02\x08\x02\x01\x02\x08\x02"+"\x02\x00\x00\x00\x00\x00\x00\x00"+"\x03\x00\x00\x00"+ - "\x56\x3b\x5f\xc3\x56\x3b\x5f\xc3"+"\x05\x00\x00\x00\x00\x00\x00\x00"+"\x15\x00\x00\x00"+ - "\x7f\x00\x00\x00\x7f\x00\x00\x01"+"\x02\x00\x00\x00\x00\x00\x00\x00"+"\x03\x00\x00\x00"+ + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x01\x02\x04\x00"+"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x01\x02\x04\xff"+"\x00\x00\x00\x00\x00\x00\x00\x00"+"\x01\x00\x00\x00"+ + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x01\x02\x08\x00"+"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x01\x02\x08\xff"+"\x01\x00\x00\x00\x00\x00\x00\x00"+"\x01\x00\x00\x00"+ + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x01\x02\x08\x02"+"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x01\x02\x08\x02"+"\x02\x00\x00\x00\x00\x00\x00\x00"+"\x03\x00\x00\x00"+ + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x56\x3b\x5f\xc3"+"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x56\x3b\x5f\xc3"+"\x05\x00\x00\x00\x00\x00\x00\x00"+"\x15\x00\x00\x00"+ + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x7f\x00\x00\x00"+"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x7f\x00\x00\x01"+"\x02\x00\x00\x00\x00\x00\x00\x00"+"\x03\x00\x00\x00"+ "abeffsomething:more detail", buf.String()) }