mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-29 04:55:31 +00:00
net/packet, wgengine{,/filter}: remove net/packet IPProto forwarding consts
Only use the ones in types/ipproto now. Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
parent
01b90df2fa
commit
1eb95c7e32
@ -4,7 +4,11 @@
|
|||||||
|
|
||||||
package packet
|
package packet
|
||||||
|
|
||||||
import "encoding/binary"
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
|
||||||
|
"tailscale.com/types/ipproto"
|
||||||
|
)
|
||||||
|
|
||||||
// icmp4HeaderLength is the size of the ICMPv4 packet header, not
|
// icmp4HeaderLength is the size of the ICMPv4 packet header, not
|
||||||
// including the outer IP layer or the variable "response data"
|
// including the outer IP layer or the variable "response data"
|
||||||
@ -66,7 +70,7 @@ func (h ICMP4Header) Marshal(buf []byte) error {
|
|||||||
return errLargePacket
|
return errLargePacket
|
||||||
}
|
}
|
||||||
// The caller does not need to set this.
|
// The caller does not need to set this.
|
||||||
h.IPProto = ICMPv4
|
h.IPProto = ipproto.ICMPv4
|
||||||
|
|
||||||
buf[20] = uint8(h.Type)
|
buf[20] = uint8(h.Type)
|
||||||
buf[21] = uint8(h.Code)
|
buf[21] = uint8(h.Code)
|
||||||
|
@ -15,17 +15,7 @@
|
|||||||
"tailscale.com/types/strbuilder"
|
"tailscale.com/types/strbuilder"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const unknown = ipproto.Unknown
|
||||||
Unknown = ipproto.Unknown
|
|
||||||
TCP = ipproto.TCP
|
|
||||||
UDP = ipproto.UDP
|
|
||||||
SCTP = ipproto.SCTP
|
|
||||||
IGMP = ipproto.IGMP
|
|
||||||
ICMPv4 = ipproto.ICMPv4
|
|
||||||
ICMPv6 = ipproto.ICMPv6
|
|
||||||
TSMP = ipproto.TSMP
|
|
||||||
Fragment = ipproto.Fragment
|
|
||||||
)
|
|
||||||
|
|
||||||
// RFC1858: prevent overlapping fragment attacks.
|
// RFC1858: prevent overlapping fragment attacks.
|
||||||
const minFrag = 60 + 20 // max IPv4 header + basic TCP header
|
const minFrag = 60 + 20 // max IPv4 header + basic TCP header
|
||||||
@ -113,7 +103,7 @@ func (q *Parsed) Decode(b []byte) {
|
|||||||
|
|
||||||
if len(b) < 1 {
|
if len(b) < 1 {
|
||||||
q.IPVersion = 0
|
q.IPVersion = 0
|
||||||
q.IPProto = Unknown
|
q.IPProto = unknown
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +115,7 @@ func (q *Parsed) Decode(b []byte) {
|
|||||||
q.decode6(b)
|
q.decode6(b)
|
||||||
default:
|
default:
|
||||||
q.IPVersion = 0
|
q.IPVersion = 0
|
||||||
q.IPProto = Unknown
|
q.IPProto = unknown
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,7 +128,7 @@ func (q *Parsed) StuffForTesting(len int) {
|
|||||||
func (q *Parsed) decode4(b []byte) {
|
func (q *Parsed) decode4(b []byte) {
|
||||||
if len(b) < ip4HeaderLength {
|
if len(b) < ip4HeaderLength {
|
||||||
q.IPVersion = 0
|
q.IPVersion = 0
|
||||||
q.IPProto = Unknown
|
q.IPProto = unknown
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,7 +137,7 @@ func (q *Parsed) decode4(b []byte) {
|
|||||||
q.length = int(binary.BigEndian.Uint16(b[2:4]))
|
q.length = int(binary.BigEndian.Uint16(b[2:4]))
|
||||||
if len(b) < q.length {
|
if len(b) < q.length {
|
||||||
// Packet was cut off before full IPv4 length.
|
// Packet was cut off before full IPv4 length.
|
||||||
q.IPProto = Unknown
|
q.IPProto = unknown
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,7 +148,7 @@ func (q *Parsed) decode4(b []byte) {
|
|||||||
q.subofs = int((b[0] & 0x0F) << 2)
|
q.subofs = int((b[0] & 0x0F) << 2)
|
||||||
if q.subofs > q.length {
|
if q.subofs > q.length {
|
||||||
// next-proto starts beyond end of packet.
|
// next-proto starts beyond end of packet.
|
||||||
q.IPProto = Unknown
|
q.IPProto = unknown
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
sub := b[q.subofs:]
|
sub := b[q.subofs:]
|
||||||
@ -183,29 +173,29 @@ func (q *Parsed) decode4(b []byte) {
|
|||||||
// This is the first fragment
|
// This is the first fragment
|
||||||
if moreFrags && len(sub) < minFrag {
|
if moreFrags && len(sub) < minFrag {
|
||||||
// Suspiciously short first fragment, dump it.
|
// Suspiciously short first fragment, dump it.
|
||||||
q.IPProto = Unknown
|
q.IPProto = unknown
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// otherwise, this is either non-fragmented (the usual case)
|
// otherwise, this is either non-fragmented (the usual case)
|
||||||
// or a big enough initial fragment that we can read the
|
// or a big enough initial fragment that we can read the
|
||||||
// whole subprotocol header.
|
// whole subprotocol header.
|
||||||
switch q.IPProto {
|
switch q.IPProto {
|
||||||
case ICMPv4:
|
case ipproto.ICMPv4:
|
||||||
if len(sub) < icmp4HeaderLength {
|
if len(sub) < icmp4HeaderLength {
|
||||||
q.IPProto = Unknown
|
q.IPProto = unknown
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
q.Src.Port = 0
|
q.Src.Port = 0
|
||||||
q.Dst.Port = 0
|
q.Dst.Port = 0
|
||||||
q.dataofs = q.subofs + icmp4HeaderLength
|
q.dataofs = q.subofs + icmp4HeaderLength
|
||||||
return
|
return
|
||||||
case IGMP:
|
case ipproto.IGMP:
|
||||||
// Keep IPProto, but don't parse anything else
|
// Keep IPProto, but don't parse anything else
|
||||||
// out.
|
// out.
|
||||||
return
|
return
|
||||||
case TCP:
|
case ipproto.TCP:
|
||||||
if len(sub) < tcpHeaderLength {
|
if len(sub) < tcpHeaderLength {
|
||||||
q.IPProto = Unknown
|
q.IPProto = unknown
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
q.Src.Port = binary.BigEndian.Uint16(sub[0:2])
|
q.Src.Port = binary.BigEndian.Uint16(sub[0:2])
|
||||||
@ -214,29 +204,29 @@ func (q *Parsed) decode4(b []byte) {
|
|||||||
headerLength := (sub[12] & 0xF0) >> 2
|
headerLength := (sub[12] & 0xF0) >> 2
|
||||||
q.dataofs = q.subofs + int(headerLength)
|
q.dataofs = q.subofs + int(headerLength)
|
||||||
return
|
return
|
||||||
case UDP:
|
case ipproto.UDP:
|
||||||
if len(sub) < udpHeaderLength {
|
if len(sub) < udpHeaderLength {
|
||||||
q.IPProto = Unknown
|
q.IPProto = unknown
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
q.Src.Port = binary.BigEndian.Uint16(sub[0:2])
|
q.Src.Port = binary.BigEndian.Uint16(sub[0:2])
|
||||||
q.Dst.Port = binary.BigEndian.Uint16(sub[2:4])
|
q.Dst.Port = binary.BigEndian.Uint16(sub[2:4])
|
||||||
q.dataofs = q.subofs + udpHeaderLength
|
q.dataofs = q.subofs + udpHeaderLength
|
||||||
return
|
return
|
||||||
case SCTP:
|
case ipproto.SCTP:
|
||||||
if len(sub) < sctpHeaderLength {
|
if len(sub) < sctpHeaderLength {
|
||||||
q.IPProto = Unknown
|
q.IPProto = unknown
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
q.Src.Port = binary.BigEndian.Uint16(sub[0:2])
|
q.Src.Port = binary.BigEndian.Uint16(sub[0:2])
|
||||||
q.Dst.Port = binary.BigEndian.Uint16(sub[2:4])
|
q.Dst.Port = binary.BigEndian.Uint16(sub[2:4])
|
||||||
return
|
return
|
||||||
case TSMP:
|
case ipproto.TSMP:
|
||||||
// Inter-tailscale messages.
|
// Inter-tailscale messages.
|
||||||
q.dataofs = q.subofs
|
q.dataofs = q.subofs
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
q.IPProto = Unknown
|
q.IPProto = unknown
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -244,7 +234,7 @@ func (q *Parsed) decode4(b []byte) {
|
|||||||
if fragOfs < minFrag {
|
if fragOfs < minFrag {
|
||||||
// First frag was suspiciously short, so we can't
|
// First frag was suspiciously short, so we can't
|
||||||
// trust the followup either.
|
// trust the followup either.
|
||||||
q.IPProto = Unknown
|
q.IPProto = unknown
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// otherwise, we have to permit the fragment to slide through.
|
// otherwise, we have to permit the fragment to slide through.
|
||||||
@ -253,7 +243,7 @@ func (q *Parsed) decode4(b []byte) {
|
|||||||
// but that would require statefulness. Anyway, receivers'
|
// but that would require statefulness. Anyway, receivers'
|
||||||
// kernels know to drop fragments where the initial fragment
|
// kernels know to drop fragments where the initial fragment
|
||||||
// doesn't arrive.
|
// doesn't arrive.
|
||||||
q.IPProto = Fragment
|
q.IPProto = ipproto.Fragment
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -261,7 +251,7 @@ func (q *Parsed) decode4(b []byte) {
|
|||||||
func (q *Parsed) decode6(b []byte) {
|
func (q *Parsed) decode6(b []byte) {
|
||||||
if len(b) < ip6HeaderLength {
|
if len(b) < ip6HeaderLength {
|
||||||
q.IPVersion = 0
|
q.IPVersion = 0
|
||||||
q.IPProto = Unknown
|
q.IPProto = unknown
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -269,7 +259,7 @@ func (q *Parsed) decode6(b []byte) {
|
|||||||
q.length = int(binary.BigEndian.Uint16(b[4:6])) + ip6HeaderLength
|
q.length = int(binary.BigEndian.Uint16(b[4:6])) + ip6HeaderLength
|
||||||
if len(b) < q.length {
|
if len(b) < q.length {
|
||||||
// Packet was cut off before the full IPv6 length.
|
// Packet was cut off before the full IPv6 length.
|
||||||
q.IPProto = Unknown
|
q.IPProto = unknown
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -295,17 +285,17 @@ func (q *Parsed) decode6(b []byte) {
|
|||||||
sub = sub[:len(sub):len(sub)] // help the compiler do bounds check elimination
|
sub = sub[:len(sub):len(sub)] // help the compiler do bounds check elimination
|
||||||
|
|
||||||
switch q.IPProto {
|
switch q.IPProto {
|
||||||
case ICMPv6:
|
case ipproto.ICMPv6:
|
||||||
if len(sub) < icmp6HeaderLength {
|
if len(sub) < icmp6HeaderLength {
|
||||||
q.IPProto = Unknown
|
q.IPProto = unknown
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
q.Src.Port = 0
|
q.Src.Port = 0
|
||||||
q.Dst.Port = 0
|
q.Dst.Port = 0
|
||||||
q.dataofs = q.subofs + icmp6HeaderLength
|
q.dataofs = q.subofs + icmp6HeaderLength
|
||||||
case TCP:
|
case ipproto.TCP:
|
||||||
if len(sub) < tcpHeaderLength {
|
if len(sub) < tcpHeaderLength {
|
||||||
q.IPProto = Unknown
|
q.IPProto = unknown
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
q.Src.Port = binary.BigEndian.Uint16(sub[0:2])
|
q.Src.Port = binary.BigEndian.Uint16(sub[0:2])
|
||||||
@ -314,28 +304,28 @@ func (q *Parsed) decode6(b []byte) {
|
|||||||
headerLength := (sub[12] & 0xF0) >> 2
|
headerLength := (sub[12] & 0xF0) >> 2
|
||||||
q.dataofs = q.subofs + int(headerLength)
|
q.dataofs = q.subofs + int(headerLength)
|
||||||
return
|
return
|
||||||
case UDP:
|
case ipproto.UDP:
|
||||||
if len(sub) < udpHeaderLength {
|
if len(sub) < udpHeaderLength {
|
||||||
q.IPProto = Unknown
|
q.IPProto = unknown
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
q.Src.Port = binary.BigEndian.Uint16(sub[0:2])
|
q.Src.Port = binary.BigEndian.Uint16(sub[0:2])
|
||||||
q.Dst.Port = binary.BigEndian.Uint16(sub[2:4])
|
q.Dst.Port = binary.BigEndian.Uint16(sub[2:4])
|
||||||
q.dataofs = q.subofs + udpHeaderLength
|
q.dataofs = q.subofs + udpHeaderLength
|
||||||
case SCTP:
|
case ipproto.SCTP:
|
||||||
if len(sub) < sctpHeaderLength {
|
if len(sub) < sctpHeaderLength {
|
||||||
q.IPProto = Unknown
|
q.IPProto = unknown
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
q.Src.Port = binary.BigEndian.Uint16(sub[0:2])
|
q.Src.Port = binary.BigEndian.Uint16(sub[0:2])
|
||||||
q.Dst.Port = binary.BigEndian.Uint16(sub[2:4])
|
q.Dst.Port = binary.BigEndian.Uint16(sub[2:4])
|
||||||
return
|
return
|
||||||
case TSMP:
|
case ipproto.TSMP:
|
||||||
// Inter-tailscale messages.
|
// Inter-tailscale messages.
|
||||||
q.dataofs = q.subofs
|
q.dataofs = q.subofs
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
q.IPProto = Unknown
|
q.IPProto = unknown
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -396,13 +386,13 @@ func (q *Parsed) IsTCPSyn() bool {
|
|||||||
// IsError reports whether q is an ICMP "Error" packet.
|
// IsError reports whether q is an ICMP "Error" packet.
|
||||||
func (q *Parsed) IsError() bool {
|
func (q *Parsed) IsError() bool {
|
||||||
switch q.IPProto {
|
switch q.IPProto {
|
||||||
case ICMPv4:
|
case ipproto.ICMPv4:
|
||||||
if len(q.b) < q.subofs+8 {
|
if len(q.b) < q.subofs+8 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
t := ICMP4Type(q.b[q.subofs])
|
t := ICMP4Type(q.b[q.subofs])
|
||||||
return t == ICMP4Unreachable || t == ICMP4TimeExceeded
|
return t == ICMP4Unreachable || t == ICMP4TimeExceeded
|
||||||
case ICMPv6:
|
case ipproto.ICMPv6:
|
||||||
if len(q.b) < q.subofs+8 {
|
if len(q.b) < q.subofs+8 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -416,9 +406,9 @@ func (q *Parsed) IsError() bool {
|
|||||||
// IsEchoRequest reports whether q is an ICMP Echo Request.
|
// IsEchoRequest reports whether q is an ICMP Echo Request.
|
||||||
func (q *Parsed) IsEchoRequest() bool {
|
func (q *Parsed) IsEchoRequest() bool {
|
||||||
switch q.IPProto {
|
switch q.IPProto {
|
||||||
case ICMPv4:
|
case ipproto.ICMPv4:
|
||||||
return len(q.b) >= q.subofs+8 && ICMP4Type(q.b[q.subofs]) == ICMP4EchoRequest && ICMP4Code(q.b[q.subofs+1]) == ICMP4NoCode
|
return len(q.b) >= q.subofs+8 && ICMP4Type(q.b[q.subofs]) == ICMP4EchoRequest && ICMP4Code(q.b[q.subofs+1]) == ICMP4NoCode
|
||||||
case ICMPv6:
|
case ipproto.ICMPv6:
|
||||||
return len(q.b) >= q.subofs+8 && ICMP6Type(q.b[q.subofs]) == ICMP6EchoRequest && ICMP6Code(q.b[q.subofs+1]) == ICMP6NoCode
|
return len(q.b) >= q.subofs+8 && ICMP6Type(q.b[q.subofs]) == ICMP6EchoRequest && ICMP6Code(q.b[q.subofs+1]) == ICMP6NoCode
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
@ -428,9 +418,9 @@ func (q *Parsed) IsEchoRequest() bool {
|
|||||||
// IsEchoRequest reports whether q is an IPv4 ICMP Echo Response.
|
// IsEchoRequest reports whether q is an IPv4 ICMP Echo Response.
|
||||||
func (q *Parsed) IsEchoResponse() bool {
|
func (q *Parsed) IsEchoResponse() bool {
|
||||||
switch q.IPProto {
|
switch q.IPProto {
|
||||||
case ICMPv4:
|
case ipproto.ICMPv4:
|
||||||
return len(q.b) >= q.subofs+8 && ICMP4Type(q.b[q.subofs]) == ICMP4EchoReply && ICMP4Code(q.b[q.subofs+1]) == ICMP4NoCode
|
return len(q.b) >= q.subofs+8 && ICMP4Type(q.b[q.subofs]) == ICMP4EchoReply && ICMP4Code(q.b[q.subofs+1]) == ICMP4NoCode
|
||||||
case ICMPv6:
|
case ipproto.ICMPv6:
|
||||||
return len(q.b) >= q.subofs+8 && ICMP6Type(q.b[q.subofs]) == ICMP6EchoReply && ICMP6Code(q.b[q.subofs+1]) == ICMP6NoCode
|
return len(q.b) >= q.subofs+8 && ICMP6Type(q.b[q.subofs]) == ICMP6EchoReply && ICMP6Code(q.b[q.subofs+1]) == ICMP6NoCode
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
|
@ -10,6 +10,19 @@
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"inet.af/netaddr"
|
"inet.af/netaddr"
|
||||||
|
"tailscale.com/types/ipproto"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
Unknown = ipproto.Unknown
|
||||||
|
TCP = ipproto.TCP
|
||||||
|
UDP = ipproto.UDP
|
||||||
|
SCTP = ipproto.SCTP
|
||||||
|
IGMP = ipproto.IGMP
|
||||||
|
ICMPv4 = ipproto.ICMPv4
|
||||||
|
ICMPv6 = ipproto.ICMPv6
|
||||||
|
TSMP = ipproto.TSMP
|
||||||
|
Fragment = ipproto.Fragment
|
||||||
)
|
)
|
||||||
|
|
||||||
func mustIPPort(s string) netaddr.IPPort {
|
func mustIPPort(s string) netaddr.IPPort {
|
||||||
|
@ -139,7 +139,7 @@ func (h TailscaleRejectedHeader) Marshal(buf []byte) error {
|
|||||||
}
|
}
|
||||||
if h.Src.IP.Is4() {
|
if h.Src.IP.Is4() {
|
||||||
iph := IP4Header{
|
iph := IP4Header{
|
||||||
IPProto: TSMP,
|
IPProto: ipproto.TSMP,
|
||||||
Src: h.IPSrc,
|
Src: h.IPSrc,
|
||||||
Dst: h.IPDst,
|
Dst: h.IPDst,
|
||||||
}
|
}
|
||||||
@ -147,7 +147,7 @@ func (h TailscaleRejectedHeader) Marshal(buf []byte) error {
|
|||||||
buf = buf[ip4HeaderLength:]
|
buf = buf[ip4HeaderLength:]
|
||||||
} else if h.Src.IP.Is6() {
|
} else if h.Src.IP.Is6() {
|
||||||
iph := IP6Header{
|
iph := IP6Header{
|
||||||
IPProto: TSMP,
|
IPProto: ipproto.TSMP,
|
||||||
Src: h.IPSrc,
|
Src: h.IPSrc,
|
||||||
Dst: h.IPDst,
|
Dst: h.IPDst,
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,11 @@
|
|||||||
|
|
||||||
package packet
|
package packet
|
||||||
|
|
||||||
import "encoding/binary"
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
|
||||||
|
"tailscale.com/types/ipproto"
|
||||||
|
)
|
||||||
|
|
||||||
// udpHeaderLength is the size of the UDP packet header, not including
|
// udpHeaderLength is the size of the UDP packet header, not including
|
||||||
// the outer IP header.
|
// the outer IP header.
|
||||||
@ -31,7 +35,7 @@ func (h UDP4Header) Marshal(buf []byte) error {
|
|||||||
return errLargePacket
|
return errLargePacket
|
||||||
}
|
}
|
||||||
// The caller does not need to set this.
|
// The caller does not need to set this.
|
||||||
h.IPProto = UDP
|
h.IPProto = ipproto.UDP
|
||||||
|
|
||||||
length := len(buf) - h.IP4Header.Len()
|
length := len(buf) - h.IP4Header.Len()
|
||||||
binary.BigEndian.PutUint16(buf[20:22], h.SrcPort)
|
binary.BigEndian.PutUint16(buf[20:22], h.SrcPort)
|
||||||
|
@ -4,7 +4,11 @@
|
|||||||
|
|
||||||
package packet
|
package packet
|
||||||
|
|
||||||
import "encoding/binary"
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
|
||||||
|
"tailscale.com/types/ipproto"
|
||||||
|
)
|
||||||
|
|
||||||
// UDP6Header is an IPv6+UDP header.
|
// UDP6Header is an IPv6+UDP header.
|
||||||
type UDP6Header struct {
|
type UDP6Header struct {
|
||||||
@ -27,7 +31,7 @@ func (h UDP6Header) Marshal(buf []byte) error {
|
|||||||
return errLargePacket
|
return errLargePacket
|
||||||
}
|
}
|
||||||
// The caller does not need to set this.
|
// The caller does not need to set this.
|
||||||
h.IPProto = UDP
|
h.IPProto = ipproto.UDP
|
||||||
|
|
||||||
length := len(buf) - h.IP6Header.Len()
|
length := len(buf) - h.IP6Header.Len()
|
||||||
binary.BigEndian.PutUint16(buf[40:42], h.SrcPort)
|
binary.BigEndian.PutUint16(buf[40:42], h.SrcPort)
|
||||||
|
@ -268,7 +268,7 @@ func (f *Filter) CheckTCP(srcIP, dstIP netaddr.IP, dstPort uint16) Response {
|
|||||||
}
|
}
|
||||||
pkt.Src.IP = srcIP
|
pkt.Src.IP = srcIP
|
||||||
pkt.Dst.IP = dstIP
|
pkt.Dst.IP = dstIP
|
||||||
pkt.IPProto = packet.TCP
|
pkt.IPProto = ipproto.TCP
|
||||||
pkt.TCPFlags = packet.TCPSyn
|
pkt.TCPFlags = packet.TCPSyn
|
||||||
pkt.Src.Port = 0
|
pkt.Src.Port = 0
|
||||||
pkt.Dst.Port = dstPort
|
pkt.Dst.Port = dstPort
|
||||||
@ -326,7 +326,7 @@ func (f *Filter) runIn4(q *packet.Parsed) (r Response, why string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch q.IPProto {
|
switch q.IPProto {
|
||||||
case packet.ICMPv4:
|
case ipproto.ICMPv4:
|
||||||
if q.IsEchoResponse() || q.IsError() {
|
if q.IsEchoResponse() || q.IsError() {
|
||||||
// ICMP responses are allowed.
|
// ICMP responses are allowed.
|
||||||
// TODO(apenwarr): consider using conntrack state.
|
// TODO(apenwarr): consider using conntrack state.
|
||||||
@ -338,7 +338,7 @@ func (f *Filter) runIn4(q *packet.Parsed) (r Response, why string) {
|
|||||||
// If any port is open to an IP, allow ICMP to it.
|
// If any port is open to an IP, allow ICMP to it.
|
||||||
return Accept, "icmp ok"
|
return Accept, "icmp ok"
|
||||||
}
|
}
|
||||||
case packet.TCP:
|
case ipproto.TCP:
|
||||||
// For TCP, we want to allow *outgoing* connections,
|
// For TCP, we want to allow *outgoing* connections,
|
||||||
// which means we want to allow return packets on those
|
// which means we want to allow return packets on those
|
||||||
// connections. To make this restriction work, we need to
|
// connections. To make this restriction work, we need to
|
||||||
@ -353,7 +353,7 @@ func (f *Filter) runIn4(q *packet.Parsed) (r Response, why string) {
|
|||||||
if f.matches4.match(q) {
|
if f.matches4.match(q) {
|
||||||
return Accept, "tcp ok"
|
return Accept, "tcp ok"
|
||||||
}
|
}
|
||||||
case packet.UDP, packet.SCTP:
|
case ipproto.UDP, ipproto.SCTP:
|
||||||
t := flowtrack.Tuple{Proto: q.IPProto, Src: q.Src, Dst: q.Dst}
|
t := flowtrack.Tuple{Proto: q.IPProto, Src: q.Src, Dst: q.Dst}
|
||||||
|
|
||||||
f.state.mu.Lock()
|
f.state.mu.Lock()
|
||||||
@ -366,7 +366,7 @@ func (f *Filter) runIn4(q *packet.Parsed) (r Response, why string) {
|
|||||||
if f.matches4.match(q) {
|
if f.matches4.match(q) {
|
||||||
return Accept, "ok"
|
return Accept, "ok"
|
||||||
}
|
}
|
||||||
case packet.TSMP:
|
case ipproto.TSMP:
|
||||||
return Accept, "tsmp ok"
|
return Accept, "tsmp ok"
|
||||||
default:
|
default:
|
||||||
return Drop, "Unknown proto"
|
return Drop, "Unknown proto"
|
||||||
@ -383,7 +383,7 @@ func (f *Filter) runIn6(q *packet.Parsed) (r Response, why string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch q.IPProto {
|
switch q.IPProto {
|
||||||
case packet.ICMPv6:
|
case ipproto.ICMPv6:
|
||||||
if q.IsEchoResponse() || q.IsError() {
|
if q.IsEchoResponse() || q.IsError() {
|
||||||
// ICMP responses are allowed.
|
// ICMP responses are allowed.
|
||||||
// TODO(apenwarr): consider using conntrack state.
|
// TODO(apenwarr): consider using conntrack state.
|
||||||
@ -395,7 +395,7 @@ func (f *Filter) runIn6(q *packet.Parsed) (r Response, why string) {
|
|||||||
// If any port is open to an IP, allow ICMP to it.
|
// If any port is open to an IP, allow ICMP to it.
|
||||||
return Accept, "icmp ok"
|
return Accept, "icmp ok"
|
||||||
}
|
}
|
||||||
case packet.TCP:
|
case ipproto.TCP:
|
||||||
// For TCP, we want to allow *outgoing* connections,
|
// For TCP, we want to allow *outgoing* connections,
|
||||||
// which means we want to allow return packets on those
|
// which means we want to allow return packets on those
|
||||||
// connections. To make this restriction work, we need to
|
// connections. To make this restriction work, we need to
|
||||||
@ -404,13 +404,13 @@ func (f *Filter) runIn6(q *packet.Parsed) (r Response, why string) {
|
|||||||
// can't be initiated without first sending a SYN.
|
// can't be initiated without first sending a SYN.
|
||||||
// It happens to also be much faster.
|
// It happens to also be much faster.
|
||||||
// TODO(apenwarr): Skip the rest of decoding in this path?
|
// TODO(apenwarr): Skip the rest of decoding in this path?
|
||||||
if q.IPProto == packet.TCP && !q.IsTCPSyn() {
|
if q.IPProto == ipproto.TCP && !q.IsTCPSyn() {
|
||||||
return Accept, "tcp non-syn"
|
return Accept, "tcp non-syn"
|
||||||
}
|
}
|
||||||
if f.matches6.match(q) {
|
if f.matches6.match(q) {
|
||||||
return Accept, "tcp ok"
|
return Accept, "tcp ok"
|
||||||
}
|
}
|
||||||
case packet.UDP, packet.SCTP:
|
case ipproto.UDP, ipproto.SCTP:
|
||||||
t := flowtrack.Tuple{Proto: q.IPProto, Src: q.Src, Dst: q.Dst}
|
t := flowtrack.Tuple{Proto: q.IPProto, Src: q.Src, Dst: q.Dst}
|
||||||
|
|
||||||
f.state.mu.Lock()
|
f.state.mu.Lock()
|
||||||
@ -488,11 +488,11 @@ func (f *Filter) pre(q *packet.Parsed, rf RunFlags, dir direction) Response {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch q.IPProto {
|
switch q.IPProto {
|
||||||
case packet.Unknown:
|
case ipproto.Unknown:
|
||||||
// Unknown packets are dangerous; always drop them.
|
// Unknown packets are dangerous; always drop them.
|
||||||
f.logRateLimit(rf, q, dir, Drop, "unknown")
|
f.logRateLimit(rf, q, dir, Drop, "unknown")
|
||||||
return Drop
|
return Drop
|
||||||
case packet.Fragment:
|
case ipproto.Fragment:
|
||||||
// Fragments after the first always need to be passed through.
|
// Fragments after the first always need to be passed through.
|
||||||
// Very small fragments are considered Junk by Parsed.
|
// Very small fragments are considered Junk by Parsed.
|
||||||
f.logRateLimit(rf, q, dir, Accept, "fragment")
|
f.logRateLimit(rf, q, dir, Accept, "fragment")
|
||||||
@ -516,5 +516,5 @@ func omitDropLogging(p *packet.Parsed, dir direction) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return p.Dst.IP.IsMulticast() || (p.Dst.IP.IsLinkLocalUnicast() && p.Dst.IP != gcpDNSAddr) || p.IPProto == packet.IGMP
|
return p.Dst.IP.IsMulticast() || (p.Dst.IP.IsLinkLocalUnicast() && p.Dst.IP != gcpDNSAddr) || p.IPProto == ipproto.IGMP
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ func newFilter(logf logger.Logf) *Filter {
|
|||||||
}
|
}
|
||||||
matches := []Match{
|
matches := []Match{
|
||||||
m(nets("8.1.1.1", "8.2.2.2"), netports("1.2.3.4:22", "5.6.7.8:23-24")),
|
m(nets("8.1.1.1", "8.2.2.2"), netports("1.2.3.4:22", "5.6.7.8:23-24")),
|
||||||
m(nets("9.1.1.1", "9.2.2.2"), netports("1.2.3.4:22", "5.6.7.8:23-24"), packet.SCTP),
|
m(nets("9.1.1.1", "9.2.2.2"), netports("1.2.3.4:22", "5.6.7.8:23-24"), ipproto.SCTP),
|
||||||
m(nets("8.1.1.1", "8.2.2.2"), netports("5.6.7.8:27-28")),
|
m(nets("8.1.1.1", "8.2.2.2"), netports("5.6.7.8:27-28")),
|
||||||
m(nets("2.2.2.2"), netports("8.1.1.1:22")),
|
m(nets("2.2.2.2"), netports("8.1.1.1:22")),
|
||||||
m(nets("0.0.0.0/0"), netports("100.122.98.50:*")),
|
m(nets("0.0.0.0/0"), netports("100.122.98.50:*")),
|
||||||
@ -66,48 +66,48 @@ type InOut struct {
|
|||||||
}
|
}
|
||||||
tests := []InOut{
|
tests := []InOut{
|
||||||
// allow 8.1.1.1 => 1.2.3.4:22
|
// allow 8.1.1.1 => 1.2.3.4:22
|
||||||
{Accept, parsed(packet.TCP, "8.1.1.1", "1.2.3.4", 999, 22)},
|
{Accept, parsed(ipproto.TCP, "8.1.1.1", "1.2.3.4", 999, 22)},
|
||||||
{Accept, parsed(packet.ICMPv4, "8.1.1.1", "1.2.3.4", 0, 0)},
|
{Accept, parsed(ipproto.ICMPv4, "8.1.1.1", "1.2.3.4", 0, 0)},
|
||||||
{Drop, parsed(packet.TCP, "8.1.1.1", "1.2.3.4", 0, 0)},
|
{Drop, parsed(ipproto.TCP, "8.1.1.1", "1.2.3.4", 0, 0)},
|
||||||
{Accept, parsed(packet.TCP, "8.1.1.1", "1.2.3.4", 0, 22)},
|
{Accept, parsed(ipproto.TCP, "8.1.1.1", "1.2.3.4", 0, 22)},
|
||||||
{Drop, parsed(packet.TCP, "8.1.1.1", "1.2.3.4", 0, 21)},
|
{Drop, parsed(ipproto.TCP, "8.1.1.1", "1.2.3.4", 0, 21)},
|
||||||
// allow 8.2.2.2. => 1.2.3.4:22
|
// allow 8.2.2.2. => 1.2.3.4:22
|
||||||
{Accept, parsed(packet.TCP, "8.2.2.2", "1.2.3.4", 0, 22)},
|
{Accept, parsed(ipproto.TCP, "8.2.2.2", "1.2.3.4", 0, 22)},
|
||||||
{Drop, parsed(packet.TCP, "8.2.2.2", "1.2.3.4", 0, 23)},
|
{Drop, parsed(ipproto.TCP, "8.2.2.2", "1.2.3.4", 0, 23)},
|
||||||
{Drop, parsed(packet.TCP, "8.3.3.3", "1.2.3.4", 0, 22)},
|
{Drop, parsed(ipproto.TCP, "8.3.3.3", "1.2.3.4", 0, 22)},
|
||||||
// allow 8.1.1.1 => 5.6.7.8:23-24
|
// allow 8.1.1.1 => 5.6.7.8:23-24
|
||||||
{Accept, parsed(packet.TCP, "8.1.1.1", "5.6.7.8", 0, 23)},
|
{Accept, parsed(ipproto.TCP, "8.1.1.1", "5.6.7.8", 0, 23)},
|
||||||
{Accept, parsed(packet.TCP, "8.1.1.1", "5.6.7.8", 0, 24)},
|
{Accept, parsed(ipproto.TCP, "8.1.1.1", "5.6.7.8", 0, 24)},
|
||||||
{Drop, parsed(packet.TCP, "8.1.1.3", "5.6.7.8", 0, 24)},
|
{Drop, parsed(ipproto.TCP, "8.1.1.3", "5.6.7.8", 0, 24)},
|
||||||
{Drop, parsed(packet.TCP, "8.1.1.1", "5.6.7.8", 0, 22)},
|
{Drop, parsed(ipproto.TCP, "8.1.1.1", "5.6.7.8", 0, 22)},
|
||||||
// allow * => *:443
|
// allow * => *:443
|
||||||
{Accept, parsed(packet.TCP, "17.34.51.68", "8.1.34.51", 0, 443)},
|
{Accept, parsed(ipproto.TCP, "17.34.51.68", "8.1.34.51", 0, 443)},
|
||||||
{Drop, parsed(packet.TCP, "17.34.51.68", "8.1.34.51", 0, 444)},
|
{Drop, parsed(ipproto.TCP, "17.34.51.68", "8.1.34.51", 0, 444)},
|
||||||
// allow * => 100.122.98.50:*
|
// allow * => 100.122.98.50:*
|
||||||
{Accept, parsed(packet.TCP, "17.34.51.68", "100.122.98.50", 0, 999)},
|
{Accept, parsed(ipproto.TCP, "17.34.51.68", "100.122.98.50", 0, 999)},
|
||||||
{Accept, parsed(packet.TCP, "17.34.51.68", "100.122.98.50", 0, 0)},
|
{Accept, parsed(ipproto.TCP, "17.34.51.68", "100.122.98.50", 0, 0)},
|
||||||
|
|
||||||
// allow ::1, ::2 => [2001::1]:22
|
// allow ::1, ::2 => [2001::1]:22
|
||||||
{Accept, parsed(packet.TCP, "::1", "2001::1", 0, 22)},
|
{Accept, parsed(ipproto.TCP, "::1", "2001::1", 0, 22)},
|
||||||
{Accept, parsed(packet.ICMPv6, "::1", "2001::1", 0, 0)},
|
{Accept, parsed(ipproto.ICMPv6, "::1", "2001::1", 0, 0)},
|
||||||
{Accept, parsed(packet.TCP, "::2", "2001::1", 0, 22)},
|
{Accept, parsed(ipproto.TCP, "::2", "2001::1", 0, 22)},
|
||||||
{Accept, parsed(packet.TCP, "::2", "2001::2", 0, 22)},
|
{Accept, parsed(ipproto.TCP, "::2", "2001::2", 0, 22)},
|
||||||
{Drop, parsed(packet.TCP, "::1", "2001::1", 0, 23)},
|
{Drop, parsed(ipproto.TCP, "::1", "2001::1", 0, 23)},
|
||||||
{Drop, parsed(packet.TCP, "::1", "2001::3", 0, 22)},
|
{Drop, parsed(ipproto.TCP, "::1", "2001::3", 0, 22)},
|
||||||
{Drop, parsed(packet.TCP, "::3", "2001::1", 0, 22)},
|
{Drop, parsed(ipproto.TCP, "::3", "2001::1", 0, 22)},
|
||||||
// allow * => *:443
|
// allow * => *:443
|
||||||
{Accept, parsed(packet.TCP, "::1", "2001::1", 0, 443)},
|
{Accept, parsed(ipproto.TCP, "::1", "2001::1", 0, 443)},
|
||||||
{Drop, parsed(packet.TCP, "::1", "2001::1", 0, 444)},
|
{Drop, parsed(ipproto.TCP, "::1", "2001::1", 0, 444)},
|
||||||
|
|
||||||
// localNets prefilter - accepted by policy filter, but
|
// localNets prefilter - accepted by policy filter, but
|
||||||
// unexpected dst IP.
|
// unexpected dst IP.
|
||||||
{Drop, parsed(packet.TCP, "8.1.1.1", "16.32.48.64", 0, 443)},
|
{Drop, parsed(ipproto.TCP, "8.1.1.1", "16.32.48.64", 0, 443)},
|
||||||
{Drop, parsed(packet.TCP, "1::", "2602::1", 0, 443)},
|
{Drop, parsed(ipproto.TCP, "1::", "2602::1", 0, 443)},
|
||||||
|
|
||||||
// Don't allow protocols not specified by filter
|
// Don't allow protocols not specified by filter
|
||||||
{Drop, parsed(packet.SCTP, "8.1.1.1", "1.2.3.4", 999, 22)},
|
{Drop, parsed(ipproto.SCTP, "8.1.1.1", "1.2.3.4", 999, 22)},
|
||||||
// But SCTP is allowed for 9.1.1.1
|
// But SCTP is allowed for 9.1.1.1
|
||||||
{Accept, parsed(packet.SCTP, "9.1.1.1", "1.2.3.4", 999, 22)},
|
{Accept, parsed(ipproto.SCTP, "9.1.1.1", "1.2.3.4", 999, 22)},
|
||||||
}
|
}
|
||||||
for i, test := range tests {
|
for i, test := range tests {
|
||||||
aclFunc := acl.runIn4
|
aclFunc := acl.runIn4
|
||||||
@ -117,7 +117,7 @@ type InOut struct {
|
|||||||
if got, why := aclFunc(&test.p); test.want != got {
|
if got, why := aclFunc(&test.p); test.want != got {
|
||||||
t.Errorf("#%d runIn got=%v want=%v why=%q packet:%v", i, got, test.want, why, test.p)
|
t.Errorf("#%d runIn got=%v want=%v why=%q packet:%v", i, got, test.want, why, test.p)
|
||||||
}
|
}
|
||||||
if test.p.IPProto == packet.TCP {
|
if test.p.IPProto == ipproto.TCP {
|
||||||
var got Response
|
var got Response
|
||||||
if test.p.IPVersion == 4 {
|
if test.p.IPVersion == 4 {
|
||||||
got = acl.CheckTCP(test.p.Src.IP, test.p.Dst.IP, test.p.Dst.Port)
|
got = acl.CheckTCP(test.p.Src.IP, test.p.Dst.IP, test.p.Dst.Port)
|
||||||
@ -128,7 +128,7 @@ type InOut struct {
|
|||||||
t.Errorf("#%d CheckTCP got=%v want=%v packet:%v", i, got, test.want, test.p)
|
t.Errorf("#%d CheckTCP got=%v want=%v packet:%v", i, got, test.want, test.p)
|
||||||
}
|
}
|
||||||
// TCP and UDP are treated equivalently in the filter - verify that.
|
// TCP and UDP are treated equivalently in the filter - verify that.
|
||||||
test.p.IPProto = packet.UDP
|
test.p.IPProto = ipproto.UDP
|
||||||
if got, why := aclFunc(&test.p); test.want != got {
|
if got, why := aclFunc(&test.p); test.want != got {
|
||||||
t.Errorf("#%d runIn (UDP) got=%v want=%v why=%q packet:%v", i, got, test.want, why, test.p)
|
t.Errorf("#%d runIn (UDP) got=%v want=%v why=%q packet:%v", i, got, test.want, why, test.p)
|
||||||
}
|
}
|
||||||
@ -142,8 +142,8 @@ func TestUDPState(t *testing.T) {
|
|||||||
acl := newFilter(t.Logf)
|
acl := newFilter(t.Logf)
|
||||||
flags := LogDrops | LogAccepts
|
flags := LogDrops | LogAccepts
|
||||||
|
|
||||||
a4 := parsed(packet.UDP, "119.119.119.119", "102.102.102.102", 4242, 4343)
|
a4 := parsed(ipproto.UDP, "119.119.119.119", "102.102.102.102", 4242, 4343)
|
||||||
b4 := parsed(packet.UDP, "102.102.102.102", "119.119.119.119", 4343, 4242)
|
b4 := parsed(ipproto.UDP, "102.102.102.102", "119.119.119.119", 4343, 4242)
|
||||||
|
|
||||||
// Unsollicited UDP traffic gets dropped
|
// Unsollicited UDP traffic gets dropped
|
||||||
if got := acl.RunIn(&a4, flags); got != Drop {
|
if got := acl.RunIn(&a4, flags); got != Drop {
|
||||||
@ -158,8 +158,8 @@ func TestUDPState(t *testing.T) {
|
|||||||
t.Fatalf("incoming response packet not accepted, got=%v: %v", got, a4)
|
t.Fatalf("incoming response packet not accepted, got=%v: %v", got, a4)
|
||||||
}
|
}
|
||||||
|
|
||||||
a6 := parsed(packet.UDP, "2001::2", "2001::1", 4242, 4343)
|
a6 := parsed(ipproto.UDP, "2001::2", "2001::1", 4242, 4343)
|
||||||
b6 := parsed(packet.UDP, "2001::1", "2001::2", 4343, 4242)
|
b6 := parsed(ipproto.UDP, "2001::1", "2001::2", 4343, 4242)
|
||||||
|
|
||||||
// Unsollicited UDP traffic gets dropped
|
// Unsollicited UDP traffic gets dropped
|
||||||
if got := acl.RunIn(&a6, flags); got != Drop {
|
if got := acl.RunIn(&a6, flags); got != Drop {
|
||||||
@ -178,10 +178,10 @@ func TestUDPState(t *testing.T) {
|
|||||||
func TestNoAllocs(t *testing.T) {
|
func TestNoAllocs(t *testing.T) {
|
||||||
acl := newFilter(t.Logf)
|
acl := newFilter(t.Logf)
|
||||||
|
|
||||||
tcp4Packet := raw4(packet.TCP, "8.1.1.1", "1.2.3.4", 999, 22, 0)
|
tcp4Packet := raw4(ipproto.TCP, "8.1.1.1", "1.2.3.4", 999, 22, 0)
|
||||||
udp4Packet := raw4(packet.UDP, "8.1.1.1", "1.2.3.4", 999, 22, 0)
|
udp4Packet := raw4(ipproto.UDP, "8.1.1.1", "1.2.3.4", 999, 22, 0)
|
||||||
tcp6Packet := raw6(packet.TCP, "2001::1", "2001::2", 999, 22, 0)
|
tcp6Packet := raw6(ipproto.TCP, "2001::1", "2001::2", 999, 22, 0)
|
||||||
udp6Packet := raw6(packet.UDP, "2001::1", "2001::2", 999, 22, 0)
|
udp6Packet := raw6(ipproto.UDP, "2001::1", "2001::2", 999, 22, 0)
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
@ -262,13 +262,13 @@ func TestParseIPSet(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkFilter(b *testing.B) {
|
func BenchmarkFilter(b *testing.B) {
|
||||||
tcp4Packet := raw4(packet.TCP, "8.1.1.1", "1.2.3.4", 999, 22, 0)
|
tcp4Packet := raw4(ipproto.TCP, "8.1.1.1", "1.2.3.4", 999, 22, 0)
|
||||||
udp4Packet := raw4(packet.UDP, "8.1.1.1", "1.2.3.4", 999, 22, 0)
|
udp4Packet := raw4(ipproto.UDP, "8.1.1.1", "1.2.3.4", 999, 22, 0)
|
||||||
icmp4Packet := raw4(packet.ICMPv4, "8.1.1.1", "1.2.3.4", 0, 0, 0)
|
icmp4Packet := raw4(ipproto.ICMPv4, "8.1.1.1", "1.2.3.4", 0, 0, 0)
|
||||||
|
|
||||||
tcp6Packet := raw6(packet.TCP, "::1", "2001::1", 999, 22, 0)
|
tcp6Packet := raw6(ipproto.TCP, "::1", "2001::1", 999, 22, 0)
|
||||||
udp6Packet := raw6(packet.UDP, "::1", "2001::1", 999, 22, 0)
|
udp6Packet := raw6(ipproto.UDP, "::1", "2001::1", 999, 22, 0)
|
||||||
icmp6Packet := raw6(packet.ICMPv6, "::1", "2001::1", 0, 0, 0)
|
icmp6Packet := raw6(ipproto.ICMPv6, "::1", "2001::1", 0, 0, 0)
|
||||||
|
|
||||||
benches := []struct {
|
benches := []struct {
|
||||||
name string
|
name string
|
||||||
@ -315,11 +315,11 @@ func TestPreFilter(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{"empty", Accept, []byte{}},
|
{"empty", Accept, []byte{}},
|
||||||
{"short", Drop, []byte("short")},
|
{"short", Drop, []byte("short")},
|
||||||
{"junk", Drop, raw4default(packet.Unknown, 10)},
|
{"junk", Drop, raw4default(ipproto.Unknown, 10)},
|
||||||
{"fragment", Accept, raw4default(packet.Fragment, 40)},
|
{"fragment", Accept, raw4default(ipproto.Fragment, 40)},
|
||||||
{"tcp", noVerdict, raw4default(packet.TCP, 0)},
|
{"tcp", noVerdict, raw4default(ipproto.TCP, 0)},
|
||||||
{"udp", noVerdict, raw4default(packet.UDP, 0)},
|
{"udp", noVerdict, raw4default(ipproto.UDP, 0)},
|
||||||
{"icmp", noVerdict, raw4default(packet.ICMPv4, 0)},
|
{"icmp", noVerdict, raw4default(ipproto.ICMPv4, 0)},
|
||||||
}
|
}
|
||||||
f := NewAllowNone(t.Logf, &netaddr.IPSet{})
|
f := NewAllowNone(t.Logf, &netaddr.IPSet{})
|
||||||
for _, testPacket := range packets {
|
for _, testPacket := range packets {
|
||||||
@ -341,7 +341,7 @@ func TestOmitDropLogging(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "v4_tcp_out",
|
name: "v4_tcp_out",
|
||||||
pkt: &packet.Parsed{IPVersion: 4, IPProto: packet.TCP},
|
pkt: &packet.Parsed{IPVersion: 4, IPProto: ipproto.TCP},
|
||||||
dir: out,
|
dir: out,
|
||||||
want: false,
|
want: false,
|
||||||
},
|
},
|
||||||
@ -439,73 +439,73 @@ func TestLoggingPrivacy(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "ts_to_ts_v4_out",
|
name: "ts_to_ts_v4_out",
|
||||||
pkt: &packet.Parsed{IPVersion: 4, IPProto: packet.TCP, Src: ts4, Dst: ts4},
|
pkt: &packet.Parsed{IPVersion: 4, IPProto: ipproto.TCP, Src: ts4, Dst: ts4},
|
||||||
dir: out,
|
dir: out,
|
||||||
logged: true,
|
logged: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ts_to_internet_v4_out",
|
name: "ts_to_internet_v4_out",
|
||||||
pkt: &packet.Parsed{IPVersion: 4, IPProto: packet.TCP, Src: ts4, Dst: internet4},
|
pkt: &packet.Parsed{IPVersion: 4, IPProto: ipproto.TCP, Src: ts4, Dst: internet4},
|
||||||
dir: out,
|
dir: out,
|
||||||
logged: false,
|
logged: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "internet_to_ts_v4_out",
|
name: "internet_to_ts_v4_out",
|
||||||
pkt: &packet.Parsed{IPVersion: 4, IPProto: packet.TCP, Src: internet4, Dst: ts4},
|
pkt: &packet.Parsed{IPVersion: 4, IPProto: ipproto.TCP, Src: internet4, Dst: ts4},
|
||||||
dir: out,
|
dir: out,
|
||||||
logged: false,
|
logged: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ts_to_ts_v4_in",
|
name: "ts_to_ts_v4_in",
|
||||||
pkt: &packet.Parsed{IPVersion: 4, IPProto: packet.TCP, Src: ts4, Dst: ts4},
|
pkt: &packet.Parsed{IPVersion: 4, IPProto: ipproto.TCP, Src: ts4, Dst: ts4},
|
||||||
dir: in,
|
dir: in,
|
||||||
logged: true,
|
logged: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ts_to_internet_v4_in",
|
name: "ts_to_internet_v4_in",
|
||||||
pkt: &packet.Parsed{IPVersion: 4, IPProto: packet.TCP, Src: ts4, Dst: internet4},
|
pkt: &packet.Parsed{IPVersion: 4, IPProto: ipproto.TCP, Src: ts4, Dst: internet4},
|
||||||
dir: in,
|
dir: in,
|
||||||
logged: false,
|
logged: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "internet_to_ts_v4_in",
|
name: "internet_to_ts_v4_in",
|
||||||
pkt: &packet.Parsed{IPVersion: 4, IPProto: packet.TCP, Src: internet4, Dst: ts4},
|
pkt: &packet.Parsed{IPVersion: 4, IPProto: ipproto.TCP, Src: internet4, Dst: ts4},
|
||||||
dir: in,
|
dir: in,
|
||||||
logged: false,
|
logged: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ts_to_ts_v6_out",
|
name: "ts_to_ts_v6_out",
|
||||||
pkt: &packet.Parsed{IPVersion: 6, IPProto: packet.TCP, Src: ts6, Dst: ts6},
|
pkt: &packet.Parsed{IPVersion: 6, IPProto: ipproto.TCP, Src: ts6, Dst: ts6},
|
||||||
dir: out,
|
dir: out,
|
||||||
logged: true,
|
logged: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ts_to_internet_v6_out",
|
name: "ts_to_internet_v6_out",
|
||||||
pkt: &packet.Parsed{IPVersion: 6, IPProto: packet.TCP, Src: ts6, Dst: internet6},
|
pkt: &packet.Parsed{IPVersion: 6, IPProto: ipproto.TCP, Src: ts6, Dst: internet6},
|
||||||
dir: out,
|
dir: out,
|
||||||
logged: false,
|
logged: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "internet_to_ts_v6_out",
|
name: "internet_to_ts_v6_out",
|
||||||
pkt: &packet.Parsed{IPVersion: 6, IPProto: packet.TCP, Src: internet6, Dst: ts6},
|
pkt: &packet.Parsed{IPVersion: 6, IPProto: ipproto.TCP, Src: internet6, Dst: ts6},
|
||||||
dir: out,
|
dir: out,
|
||||||
logged: false,
|
logged: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ts_to_ts_v6_in",
|
name: "ts_to_ts_v6_in",
|
||||||
pkt: &packet.Parsed{IPVersion: 6, IPProto: packet.TCP, Src: ts6, Dst: ts6},
|
pkt: &packet.Parsed{IPVersion: 6, IPProto: ipproto.TCP, Src: ts6, Dst: ts6},
|
||||||
dir: in,
|
dir: in,
|
||||||
logged: true,
|
logged: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ts_to_internet_v6_in",
|
name: "ts_to_internet_v6_in",
|
||||||
pkt: &packet.Parsed{IPVersion: 6, IPProto: packet.TCP, Src: ts6, Dst: internet6},
|
pkt: &packet.Parsed{IPVersion: 6, IPProto: ipproto.TCP, Src: ts6, Dst: internet6},
|
||||||
dir: in,
|
dir: in,
|
||||||
logged: false,
|
logged: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "internet_to_ts_v6_in",
|
name: "internet_to_ts_v6_in",
|
||||||
pkt: &packet.Parsed{IPVersion: 6, IPProto: packet.TCP, Src: internet6, Dst: ts6},
|
pkt: &packet.Parsed{IPVersion: 6, IPProto: ipproto.TCP, Src: internet6, Dst: ts6},
|
||||||
dir: in,
|
dir: in,
|
||||||
logged: false,
|
logged: false,
|
||||||
},
|
},
|
||||||
@ -607,7 +607,7 @@ func raw4(proto ipproto.Proto, src, dst string, sport, dport uint16, trimLength
|
|||||||
|
|
||||||
// UDP marshaling clobbers IPProto, so override it here.
|
// UDP marshaling clobbers IPProto, so override it here.
|
||||||
switch proto {
|
switch proto {
|
||||||
case packet.Unknown, packet.Fragment:
|
case ipproto.Unknown, ipproto.Fragment:
|
||||||
default:
|
default:
|
||||||
u.IP4Header.IPProto = proto
|
u.IP4Header.IPProto = proto
|
||||||
}
|
}
|
||||||
@ -615,7 +615,7 @@ func raw4(proto ipproto.Proto, src, dst string, sport, dport uint16, trimLength
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if proto == packet.Fragment {
|
if proto == ipproto.Fragment {
|
||||||
// Set some fragment offset. This makes the IP
|
// Set some fragment offset. This makes the IP
|
||||||
// checksum wrong, but we don't validate the checksum
|
// checksum wrong, but we don't validate the checksum
|
||||||
// when parsing.
|
// when parsing.
|
||||||
@ -751,10 +751,10 @@ func TestMatchesFromFilterRules(t *testing.T) {
|
|||||||
want: []Match{
|
want: []Match{
|
||||||
{
|
{
|
||||||
IPProto: []ipproto.Proto{
|
IPProto: []ipproto.Proto{
|
||||||
packet.TCP,
|
ipproto.TCP,
|
||||||
packet.UDP,
|
ipproto.UDP,
|
||||||
packet.ICMPv4,
|
ipproto.ICMPv4,
|
||||||
packet.ICMPv6,
|
ipproto.ICMPv6,
|
||||||
},
|
},
|
||||||
Dsts: []NetPortRange{
|
Dsts: []NetPortRange{
|
||||||
{
|
{
|
||||||
@ -776,7 +776,7 @@ func TestMatchesFromFilterRules(t *testing.T) {
|
|||||||
name: "explicit_protos",
|
name: "explicit_protos",
|
||||||
in: []tailcfg.FilterRule{
|
in: []tailcfg.FilterRule{
|
||||||
{
|
{
|
||||||
IPProto: []int{int(packet.TCP)},
|
IPProto: []int{int(ipproto.TCP)},
|
||||||
SrcIPs: []string{"100.64.1.1"},
|
SrcIPs: []string{"100.64.1.1"},
|
||||||
DstPorts: []tailcfg.NetPortRange{{
|
DstPorts: []tailcfg.NetPortRange{{
|
||||||
IP: "1.2.0.0/16",
|
IP: "1.2.0.0/16",
|
||||||
@ -787,7 +787,7 @@ func TestMatchesFromFilterRules(t *testing.T) {
|
|||||||
want: []Match{
|
want: []Match{
|
||||||
{
|
{
|
||||||
IPProto: []ipproto.Proto{
|
IPProto: []ipproto.Proto{
|
||||||
packet.TCP,
|
ipproto.TCP,
|
||||||
},
|
},
|
||||||
Dsts: []NetPortRange{
|
Dsts: []NetPortRange{
|
||||||
{
|
{
|
||||||
|
@ -9,16 +9,15 @@
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"inet.af/netaddr"
|
"inet.af/netaddr"
|
||||||
"tailscale.com/net/packet"
|
|
||||||
"tailscale.com/tailcfg"
|
"tailscale.com/tailcfg"
|
||||||
"tailscale.com/types/ipproto"
|
"tailscale.com/types/ipproto"
|
||||||
)
|
)
|
||||||
|
|
||||||
var defaultProtos = []ipproto.Proto{
|
var defaultProtos = []ipproto.Proto{
|
||||||
packet.TCP,
|
ipproto.TCP,
|
||||||
packet.UDP,
|
ipproto.UDP,
|
||||||
packet.ICMPv4,
|
ipproto.ICMPv4,
|
||||||
packet.ICMPv6,
|
ipproto.ICMPv6,
|
||||||
}
|
}
|
||||||
|
|
||||||
// MatchesFromFilterRules converts tailcfg FilterRules into Matches.
|
// MatchesFromFilterRules converts tailcfg FilterRules into Matches.
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
"tailscale.com/net/flowtrack"
|
"tailscale.com/net/flowtrack"
|
||||||
"tailscale.com/net/packet"
|
"tailscale.com/net/packet"
|
||||||
"tailscale.com/net/tsaddr"
|
"tailscale.com/net/tsaddr"
|
||||||
|
"tailscale.com/types/ipproto"
|
||||||
"tailscale.com/wgengine/filter"
|
"tailscale.com/wgengine/filter"
|
||||||
"tailscale.com/wgengine/tstun"
|
"tailscale.com/wgengine/tstun"
|
||||||
)
|
)
|
||||||
@ -68,7 +69,7 @@ func (e *userspaceEngine) noteFlowProblemFromPeer(f flowtrack.Tuple, problem pac
|
|||||||
func (e *userspaceEngine) trackOpenPreFilterIn(pp *packet.Parsed, t *tstun.TUN) (res filter.Response) {
|
func (e *userspaceEngine) trackOpenPreFilterIn(pp *packet.Parsed, t *tstun.TUN) (res filter.Response) {
|
||||||
res = filter.Accept // always
|
res = filter.Accept // always
|
||||||
|
|
||||||
if pp.IPProto == packet.TSMP {
|
if pp.IPProto == ipproto.TSMP {
|
||||||
res = filter.DropSilently
|
res = filter.DropSilently
|
||||||
rh, ok := pp.AsTailscaleRejectedHeader()
|
rh, ok := pp.AsTailscaleRejectedHeader()
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -83,7 +84,7 @@ func (e *userspaceEngine) trackOpenPreFilterIn(pp *packet.Parsed, t *tstun.TUN)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if pp.IPVersion == 0 ||
|
if pp.IPVersion == 0 ||
|
||||||
pp.IPProto != packet.TCP ||
|
pp.IPProto != ipproto.TCP ||
|
||||||
pp.TCPFlags&(packet.TCPSyn|packet.TCPRst) == 0 {
|
pp.TCPFlags&(packet.TCPSyn|packet.TCPRst) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -102,7 +103,7 @@ func (e *userspaceEngine) trackOpenPostFilterOut(pp *packet.Parsed, t *tstun.TUN
|
|||||||
res = filter.Accept // always
|
res = filter.Accept // always
|
||||||
|
|
||||||
if pp.IPVersion == 0 ||
|
if pp.IPVersion == 0 ||
|
||||||
pp.IPProto != packet.TCP ||
|
pp.IPProto != ipproto.TCP ||
|
||||||
pp.TCPFlags&packet.TCPSyn == 0 {
|
pp.TCPFlags&packet.TCPSyn == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
"github.com/tailscale/wireguard-go/tun"
|
"github.com/tailscale/wireguard-go/tun"
|
||||||
"inet.af/netaddr"
|
"inet.af/netaddr"
|
||||||
"tailscale.com/net/packet"
|
"tailscale.com/net/packet"
|
||||||
|
"tailscale.com/types/ipproto"
|
||||||
"tailscale.com/types/logger"
|
"tailscale.com/types/logger"
|
||||||
"tailscale.com/wgengine/filter"
|
"tailscale.com/wgengine/filter"
|
||||||
)
|
)
|
||||||
@ -340,7 +341,7 @@ func (t *TUN) filterIn(buf []byte) filter.Response {
|
|||||||
// Their host networking stack can translate this into ICMP
|
// Their host networking stack can translate this into ICMP
|
||||||
// or whatnot as required. But notably, their GUI or tailscale CLI
|
// or whatnot as required. But notably, their GUI or tailscale CLI
|
||||||
// can show them a rejection history with reasons.
|
// can show them a rejection history with reasons.
|
||||||
if p.IPVersion == 4 && p.IPProto == packet.TCP && p.TCPFlags&packet.TCPSyn != 0 {
|
if p.IPVersion == 4 && p.IPProto == ipproto.TCP && p.TCPFlags&packet.TCPSyn != 0 {
|
||||||
rj := packet.TailscaleRejectedHeader{
|
rj := packet.TailscaleRejectedHeader{
|
||||||
IPSrc: p.Dst.IP,
|
IPSrc: p.Dst.IP,
|
||||||
IPDst: p.Src.IP,
|
IPDst: p.Src.IP,
|
||||||
|
@ -108,8 +108,8 @@ func netports(netPorts ...string) (ret []filter.NetPortRange) {
|
|||||||
|
|
||||||
func setfilter(logf logger.Logf, tun *TUN) {
|
func setfilter(logf logger.Logf, tun *TUN) {
|
||||||
protos := []ipproto.Proto{
|
protos := []ipproto.Proto{
|
||||||
packet.TCP,
|
ipproto.TCP,
|
||||||
packet.UDP,
|
ipproto.UDP,
|
||||||
}
|
}
|
||||||
matches := []filter.Match{
|
matches := []filter.Match{
|
||||||
{IPProto: protos, Srcs: nets("5.6.7.8"), Dsts: netports("1.2.3.4:89-90")},
|
{IPProto: protos, Srcs: nets("5.6.7.8"), Dsts: netports("1.2.3.4:89-90")},
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
"tailscale.com/net/tsaddr"
|
"tailscale.com/net/tsaddr"
|
||||||
"tailscale.com/net/tshttpproxy"
|
"tailscale.com/net/tshttpproxy"
|
||||||
"tailscale.com/tailcfg"
|
"tailscale.com/tailcfg"
|
||||||
|
"tailscale.com/types/ipproto"
|
||||||
"tailscale.com/types/key"
|
"tailscale.com/types/key"
|
||||||
"tailscale.com/types/logger"
|
"tailscale.com/types/logger"
|
||||||
"tailscale.com/types/netmap"
|
"tailscale.com/types/netmap"
|
||||||
@ -462,7 +463,7 @@ func (e *userspaceEngine) isLocalAddr(ip netaddr.IP) bool {
|
|||||||
|
|
||||||
// handleDNS is an outbound pre-filter resolving Tailscale domains.
|
// handleDNS is an outbound pre-filter resolving Tailscale domains.
|
||||||
func (e *userspaceEngine) handleDNS(p *packet.Parsed, t *tstun.TUN) filter.Response {
|
func (e *userspaceEngine) handleDNS(p *packet.Parsed, t *tstun.TUN) filter.Response {
|
||||||
if p.Dst.IP == magicDNSIP && p.Dst.Port == magicDNSPort && p.IPProto == packet.UDP {
|
if p.Dst.IP == magicDNSIP && p.Dst.Port == magicDNSPort && p.IPProto == ipproto.UDP {
|
||||||
request := tsdns.Packet{
|
request := tsdns.Packet{
|
||||||
Payload: append([]byte(nil), p.Payload()...),
|
Payload: append([]byte(nil), p.Payload()...),
|
||||||
Addr: netaddr.IPPort{IP: p.Src.IP, Port: p.Src.Port},
|
Addr: netaddr.IPPort{IP: p.Src.IP, Port: p.Src.Port},
|
||||||
|
Loading…
Reference in New Issue
Block a user