Support IPv6 blocklists

Existing packed blocklists need to be regenerated.
This commit is contained in:
Matt Joiner 2018-02-11 15:11:26 +11:00
parent 924b916b2a
commit 8d1995c4d4
4 changed files with 29 additions and 45 deletions

View File

@ -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() {

View File

@ -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 {

View File

@ -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

View File

@ -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())
}