@ -31,11 +31,11 @@ const maxBufferSize = device.MaxMessageSize
const PacketStartOffset = device . MessageTransportHeaderSize
const PacketStartOffset = device . MessageTransportHeaderSize
// MaxPacketSize is the maximum size (in bytes)
// MaxPacketSize is the maximum size (in bytes)
// of a packet that can be injected into a tstun. TUN .
// of a packet that can be injected into a tstun. Wrapper .
const MaxPacketSize = device . MaxContentSize
const MaxPacketSize = device . MaxContentSize
var (
var (
// ErrClosed is returned when attempting an operation on a closed TUN .
// ErrClosed is returned when attempting an operation on a closed Wrapper .
ErrClosed = errors . New ( "device closed" )
ErrClosed = errors . New ( "device closed" )
// ErrFiltered is returned when the acted-on packet is rejected by a filter.
// ErrFiltered is returned when the acted-on packet is rejected by a filter.
ErrFiltered = errors . New ( "packet dropped by filter" )
ErrFiltered = errors . New ( "packet dropped by filter" )
@ -52,17 +52,14 @@ var (
// do not escape through {Pre,Post}Filter{In,Out}.
// do not escape through {Pre,Post}Filter{In,Out}.
var parsedPacketPool = sync . Pool { New : func ( ) interface { } { return new ( packet . Parsed ) } }
var parsedPacketPool = sync . Pool { New : func ( ) interface { } { return new ( packet . Parsed ) } }
// FilterFunc is a packet-filtering function with access to the TUN device.
// FilterFunc is a packet-filtering function with access to the Wrapper device.
// It must not hold onto the packet struct, as its backing storage will be reused.
// It must not hold onto the packet struct, as its backing storage will be reused.
type FilterFunc func ( * packet . Parsed , * TUN ) filter . Response
type FilterFunc func ( * packet . Parsed , * Wrapper ) filter . Response
// TUN wraps a tun.Device from wireguard-go,
// Wrapper augments a tun.Device with packet filtering and injection.
// augmenting it with filtering and packet injection.
type Wrapper struct {
// All the added work happens in Read and Write:
// the other methods delegate to the underlying tdev.
type TUN struct {
logf logger . Logf
logf logger . Logf
// tdev is the underlying TUN device.
// tdev is the underlying Wrapper device.
tdev tun . Device
tdev tun . Device
closeOnce sync . Once
closeOnce sync . Once
@ -116,8 +113,8 @@ type TUN struct {
disableFilter bool
disableFilter bool
}
}
func Wrap TUN ( logf logger . Logf , tdev tun . Device ) * TUN {
func Wrap ( logf logger . Logf , tdev tun . Device ) * Wrapper {
tun := & TUN {
tun := & Wrapper {
logf : logger . WithPrefix ( logf , "tstun: " ) ,
logf : logger . WithPrefix ( logf , "tstun: " ) ,
tdev : tdev ,
tdev : tdev ,
// bufferConsumed is conceptually a condition variable:
// bufferConsumed is conceptually a condition variable:
@ -140,12 +137,12 @@ func WrapTUN(logf logger.Logf, tdev tun.Device) *TUN {
// SetDestIPActivityFuncs sets a map of funcs to run per packet
// SetDestIPActivityFuncs sets a map of funcs to run per packet
// destination (the map keys).
// destination (the map keys).
//
//
// The map ownership passes to the TUN . It must be non-nil.
// The map ownership passes to the Wrapper . It must be non-nil.
func ( t * TUN ) SetDestIPActivityFuncs ( m map [ netaddr . IP ] func ( ) ) {
func ( t * Wrapper ) SetDestIPActivityFuncs ( m map [ netaddr . IP ] func ( ) ) {
t . destIPActivity . Store ( m )
t . destIPActivity . Store ( m )
}
}
func ( t * TUN ) Close ( ) error {
func ( t * Wrapper ) Close ( ) error {
var err error
var err error
t . closeOnce . Do ( func ( ) {
t . closeOnce . Do ( func ( ) {
// Other channels need not be closed: poll will exit gracefully after this.
// Other channels need not be closed: poll will exit gracefully after this.
@ -156,30 +153,30 @@ func (t *TUN) Close() error {
return err
return err
}
}
func ( t * TUN ) Events ( ) chan tun . Event {
func ( t * Wrapper ) Events ( ) chan tun . Event {
return t . tdev . Events ( )
return t . tdev . Events ( )
}
}
func ( t * TUN ) File ( ) * os . File {
func ( t * Wrapper ) File ( ) * os . File {
return t . tdev . File ( )
return t . tdev . File ( )
}
}
func ( t * TUN ) Flush ( ) error {
func ( t * Wrapper ) Flush ( ) error {
return t . tdev . Flush ( )
return t . tdev . Flush ( )
}
}
func ( t * TUN ) MTU ( ) ( int , error ) {
func ( t * Wrapper ) MTU ( ) ( int , error ) {
return t . tdev . MTU ( )
return t . tdev . MTU ( )
}
}
func ( t * TUN ) Name ( ) ( string , error ) {
func ( t * Wrapper ) Name ( ) ( string , error ) {
return t . tdev . Name ( )
return t . tdev . Name ( )
}
}
// poll polls t.tdev.Read, placing the oldest unconsumed packet into t.buffer.
// poll polls t.tdev.Read, placing the oldest unconsumed packet into t.buffer.
// This is needed because t.tdev.Read in general may block (it does on Windows),
// This is needed because t.tdev.Read in general may block (it does on Windows),
// so packets may be stuck in t.outbound if t.Read called t.tdev.Read directly.
// so packets may be stuck in t.outbound if t.Read called t.tdev.Read directly.
func ( t * TUN ) poll ( ) {
func ( t * Wrapper ) poll ( ) {
for {
for {
select {
select {
case <- t . closed :
case <- t . closed :
@ -189,7 +186,7 @@ func (t *TUN) poll() {
}
}
// Read may use memory in t.buffer before PacketStartOffset for mandatory headers.
// Read may use memory in t.buffer before PacketStartOffset for mandatory headers.
// This is the rationale behind the tun. TUN .{Read,Write} interfaces
// This is the rationale behind the tun. Wrapper .{Read,Write} interfaces
// and the reason t.buffer has size MaxMessageSize and not MaxContentSize.
// and the reason t.buffer has size MaxMessageSize and not MaxContentSize.
n , err := t . tdev . Read ( t . buffer [ : ] , PacketStartOffset )
n , err := t . tdev . Read ( t . buffer [ : ] , PacketStartOffset )
if err != nil {
if err != nil {
@ -221,7 +218,7 @@ func (t *TUN) poll() {
var magicDNSIPPort = netaddr . MustParseIPPort ( "100.100.100.100:0" )
var magicDNSIPPort = netaddr . MustParseIPPort ( "100.100.100.100:0" )
func ( t * TUN ) filterOut ( p * packet . Parsed ) filter . Response {
func ( t * Wrapper ) filterOut ( p * packet . Parsed ) filter . Response {
// Fake ICMP echo responses to MagicDNS (100.100.100.100).
// Fake ICMP echo responses to MagicDNS (100.100.100.100).
if p . IsEchoRequest ( ) && p . Dst == magicDNSIPPort {
if p . IsEchoRequest ( ) && p . Dst == magicDNSIPPort {
header := p . ICMP4Header ( )
header := p . ICMP4Header ( )
@ -257,7 +254,7 @@ func (t *TUN) filterOut(p *packet.Parsed) filter.Response {
}
}
// noteActivity records that there was a read or write at the current time.
// noteActivity records that there was a read or write at the current time.
func ( t * TUN ) noteActivity ( ) {
func ( t * Wrapper ) noteActivity ( ) {
atomic . StoreInt64 ( & t . lastActivityAtomic , time . Now ( ) . Unix ( ) )
atomic . StoreInt64 ( & t . lastActivityAtomic , time . Now ( ) . Unix ( ) )
}
}
@ -265,12 +262,12 @@ func (t *TUN) noteActivity() {
//
//
// Its value is only accurate to roughly second granularity.
// Its value is only accurate to roughly second granularity.
// If there's never been activity, the duration is since 1970.
// If there's never been activity, the duration is since 1970.
func ( t * TUN ) IdleDuration ( ) time . Duration {
func ( t * Wrapper ) IdleDuration ( ) time . Duration {
sec := atomic . LoadInt64 ( & t . lastActivityAtomic )
sec := atomic . LoadInt64 ( & t . lastActivityAtomic )
return time . Since ( time . Unix ( sec , 0 ) )
return time . Since ( time . Unix ( sec , 0 ) )
}
}
func ( t * TUN ) Read ( buf [ ] byte , offset int ) ( int , error ) {
func ( t * Wrapper ) Read ( buf [ ] byte , offset int ) ( int , error ) {
var n int
var n int
wasInjectedPacket := false
wasInjectedPacket := false
@ -321,7 +318,7 @@ func (t *TUN) Read(buf []byte, offset int) (int, error) {
return n , nil
return n , nil
}
}
func ( t * TUN ) filterIn ( buf [ ] byte ) filter . Response {
func ( t * Wrapper ) filterIn ( buf [ ] byte ) filter . Response {
p := parsedPacketPool . Get ( ) . ( * packet . Parsed )
p := parsedPacketPool . Get ( ) . ( * packet . Parsed )
defer parsedPacketPool . Put ( p )
defer parsedPacketPool . Put ( p )
p . Decode ( buf )
p . Decode ( buf )
@ -388,7 +385,7 @@ func (t *TUN) filterIn(buf []byte) filter.Response {
// Write accepts an incoming packet. The packet begins at buf[offset:],
// Write accepts an incoming packet. The packet begins at buf[offset:],
// like wireguard-go/tun.Device.Write.
// like wireguard-go/tun.Device.Write.
func ( t * TUN ) Write ( buf [ ] byte , offset int ) ( int , error ) {
func ( t * Wrapper ) Write ( buf [ ] byte , offset int ) ( int , error ) {
if ! t . disableFilter {
if ! t . disableFilter {
res := t . filterIn ( buf [ offset : ] )
res := t . filterIn ( buf [ offset : ] )
if res == filter . DropSilently {
if res == filter . DropSilently {
@ -403,16 +400,16 @@ func (t *TUN) Write(buf []byte, offset int) (int, error) {
return t . tdev . Write ( buf , offset )
return t . tdev . Write ( buf , offset )
}
}
func ( t * TUN ) GetFilter ( ) * filter . Filter {
func ( t * Wrapper ) GetFilter ( ) * filter . Filter {
filt , _ := t . filter . Load ( ) . ( * filter . Filter )
filt , _ := t . filter . Load ( ) . ( * filter . Filter )
return filt
return filt
}
}
func ( t * TUN ) SetFilter ( filt * filter . Filter ) {
func ( t * Wrapper ) SetFilter ( filt * filter . Filter ) {
t . filter . Store ( filt )
t . filter . Store ( filt )
}
}
// InjectInboundDirect makes the TUN device behave as if a packet
// InjectInboundDirect makes the Wrapper device behave as if a packet
// with the given contents was received from the network.
// with the given contents was received from the network.
// It blocks and does not take ownership of the packet.
// It blocks and does not take ownership of the packet.
// The injected packet will not pass through inbound filters.
// The injected packet will not pass through inbound filters.
@ -420,7 +417,7 @@ func (t *TUN) SetFilter(filt *filter.Filter) {
// The packet contents are to start at &buf[offset].
// The packet contents are to start at &buf[offset].
// offset must be greater or equal to PacketStartOffset.
// offset must be greater or equal to PacketStartOffset.
// The space before &buf[offset] will be used by Wireguard.
// The space before &buf[offset] will be used by Wireguard.
func ( t * TUN ) InjectInboundDirect ( buf [ ] byte , offset int ) error {
func ( t * Wrapper ) InjectInboundDirect ( buf [ ] byte , offset int ) error {
if len ( buf ) > MaxPacketSize {
if len ( buf ) > MaxPacketSize {
return errPacketTooBig
return errPacketTooBig
}
}
@ -439,7 +436,7 @@ func (t *TUN) InjectInboundDirect(buf []byte, offset int) error {
// InjectInboundCopy takes a packet without leading space,
// InjectInboundCopy takes a packet without leading space,
// reallocates it to conform to the InjectInboundDirect interface
// reallocates it to conform to the InjectInboundDirect interface
// and calls InjectInboundDirect on it. Injecting a nil packet is a no-op.
// and calls InjectInboundDirect on it. Injecting a nil packet is a no-op.
func ( t * TUN ) InjectInboundCopy ( packet [ ] byte ) error {
func ( t * Wrapper ) InjectInboundCopy ( packet [ ] byte ) error {
// We duplicate this check from InjectInboundDirect here
// We duplicate this check from InjectInboundDirect here
// to avoid wasting an allocation on an oversized packet.
// to avoid wasting an allocation on an oversized packet.
if len ( packet ) > MaxPacketSize {
if len ( packet ) > MaxPacketSize {
@ -455,7 +452,7 @@ func (t *TUN) InjectInboundCopy(packet []byte) error {
return t . InjectInboundDirect ( buf , PacketStartOffset )
return t . InjectInboundDirect ( buf , PacketStartOffset )
}
}
func ( t * TUN ) injectOutboundPong ( pp * packet . Parsed , req packet . TSMPPingRequest ) {
func ( t * Wrapper ) injectOutboundPong ( pp * packet . Parsed , req packet . TSMPPingRequest ) {
pong := packet . TSMPPongReply {
pong := packet . TSMPPongReply {
Data : req . Data ,
Data : req . Data ,
}
}
@ -475,12 +472,12 @@ func (t *TUN) injectOutboundPong(pp *packet.Parsed, req packet.TSMPPingRequest)
t . InjectOutbound ( packet . Generate ( pong , nil ) )
t . InjectOutbound ( packet . Generate ( pong , nil ) )
}
}
// InjectOutbound makes the TUN device behave as if a packet
// InjectOutbound makes the Wrapper device behave as if a packet
// with the given contents was sent to the network.
// with the given contents was sent to the network.
// It does not block, but takes ownership of the packet.
// It does not block, but takes ownership of the packet.
// The injected packet will not pass through outbound filters.
// The injected packet will not pass through outbound filters.
// Injecting an empty packet is a no-op.
// Injecting an empty packet is a no-op.
func ( t * TUN ) InjectOutbound ( packet [ ] byte ) error {
func ( t * Wrapper ) InjectOutbound ( packet [ ] byte ) error {
if len ( packet ) > MaxPacketSize {
if len ( packet ) > MaxPacketSize {
return errPacketTooBig
return errPacketTooBig
}
}
@ -495,7 +492,7 @@ func (t *TUN) InjectOutbound(packet []byte) error {
}
}
}
}
// Unwrap returns the underlying TUN d evice.
// Unwrap returns the underlying tun.D evice.
func ( t * TUN ) Unwrap ( ) tun . Device {
func ( t * Wrapper ) Unwrap ( ) tun . Device {
return t . tdev
return t . tdev
}
}