]> Cypherpunks.ru repositories - govpn.git/commitdiff
Configure MTU on per-user basis
authorSergey Matveev <stargrave@stargrave.org>
Tue, 5 Jan 2016 17:07:14 +0000 (20:07 +0300)
committerSergey Matveev <stargrave@stargrave.org>
Tue, 5 Jan 2016 17:07:14 +0000 (20:07 +0300)
Signed-off-by: Sergey Matveev <stargrave@stargrave.org>
18 files changed:
doc/client.texi
doc/example.texi
doc/handshake.texi
doc/mtu.texi
doc/server.texi
src/govpn/cmd/govpn-client/main.go
src/govpn/cmd/govpn-client/tcp.go
src/govpn/cmd/govpn-client/udp.go
src/govpn/cmd/govpn-server/conf.go
src/govpn/cmd/govpn-server/main.go
src/govpn/cmd/govpn-server/tcp.go
src/govpn/cmd/govpn-server/udp.go
src/govpn/common.go
src/govpn/conf.go
src/govpn/handshake.go
src/govpn/peer.go
src/govpn/peer_test.go
src/govpn/tap.go

index 40f310f4e145843d6e3b7b8f4f81a0322fb5cc7e..81878d57d2b08ec13a7cdaf0a6fea55000a7397e 100644 (file)
@@ -1,11 +1,14 @@
 @node Client
 @section Client part
 
-Except for common @code{-mtu}, @code{-stats}, @code{-egd}
-options client has the following ones:
+Except for common @code{-stats}, @code{-egd} options client has the
+following ones:
 
 @table @code
 
+@item -mtu
+Expected TAP interface @ref{MTU}.
+
 @item -proto
 @ref{Network, network protocol} to use. Can be either @emph{udp}
 (default) or @emph{tcp}.
index f734c65de829ba19e5e5ede3ff47e58d9268c2e6..c2936a61414fb66484e3fd461f5d2c107f293355 100644 (file)
@@ -8,10 +8,9 @@ WiFi-reachable gateway.
 @item You have got @code{wlan0} NIC with 192.168.0/24 network on it.
 @item You want to create virtual encrypted and authenticated 172.16.0/24
 network and use it as a default transport.
-@item @code{wlan0} MTU is 1500, 20 bytes overhead per IPv4. So MTU for
-GoVPN is 1500 - 20 - 8 = 1472.
-@item During startup client and server will say that TAP interface MTU
-is 1432.
+@item Assume that outgoing GoVPN packets can be fragmented, so we do not
+bother configuring MTU of TAP interfaces. For better performance just
+lower it and check that no fragmentation of outgoing UDP packets occurs.
 @end itemize
 
 @strong{Install}. At first you must @ref{Installation, install} this
@@ -57,7 +56,6 @@ configuration file:
 server% umask 077
 server% ip addr add 192.168.0.1/24 dev wlan0
 server% tunctl -t tap10
-server% ip link set mtu 1432 dev tap10
 server% ip addr add 172.16.0.1/24 dev tap10
 server% ip link set up dev tap10
 @end example
@@ -65,7 +63,7 @@ server% ip link set up dev tap10
 @strong{Run server daemon itself}:
 
 @example
-server% govpn-server -bind 192.168.0.1:1194 -mtu 1472
+server% govpn-server -bind 192.168.0.1:1194
 @end example
 
 @strong{Prepare network on GNU/Linux IPv4 client}:
@@ -75,7 +73,6 @@ client% umask 066
 client% utils/storekey.sh key.txt
 client% ip addr add 192.168.0.2/24 dev wlan0
 client% tunctl -t tap10
-client% ip link set mtu 1432 dev tap10
 client% ip addr add 172.16.0.2/24 dev tap10
 client% ip link set up dev tap10
 client% ip route add default via 172.16.0.1
@@ -87,8 +84,7 @@ client% govpn-client \
     -key key.txt \
     -verifier '$argon2d$m=4096,t=128,p=1$bwR5VjeCYIQaa8SeaI3rqg' \
     -iface tap10 \
-    -remote 192.168.0.1:1194 \
-    -mtu 1472
+    -remote 192.168.0.1:1194
 @end example
 
 @strong{FreeBSD IPv6 similar client-server example}:
@@ -101,7 +97,7 @@ server% govpn-server -bind "fe80::1%em0"
 @example
 client% ifconfig me0 inet6 -ifdisabled auto_linklocal
 client% ifconfig tap10
-client% ifconfig tap10 inet6 fc00::2/96 mtu 1412 up
+client% ifconfig tap10 inet6 fc00::2/96 up
 client% route -6 add default fc00::1
 client% govpn-client \
     -key key.txt \
index b445985240b447553293b1ff08537b790fa679ec..b71ac489a3f9ce2663dd227eb3ba1905445a63fc 100644 (file)
@@ -9,7 +9,7 @@ a key. It is used to transmit identity and to mark packet as handshake
 message.
 
 If @ref{Noise} is enabled, then junk data is inserted before
-@code{IDtag} to full up packet to MTU's size.
+@code{IDtag} to fill up packet to MTU's size.
 
 @strong{Preparation stage}:
 
index ef0db05ebc6343fb7ff403eccf09983ad6afd952..9c958cd383533381d4113a5fddab8eba8bb712dd 100644 (file)
@@ -1,12 +1,11 @@
 @node MTU
 @section Maximum Transmission Unit
 
-MTU command line argument is maximum allowable size of outgoing GoVPN's
-packets. It varies and depends on your environment, so probably has to
-be tuned. By default MTU equals to 1452 bytes: 40 bytes per IPv6 and 8
-bytes per UDP.
+MTU option tells what maximum transmission unit is expected to get from
+TAP interface. It is per-user configuration. If the program gets bigger
+size packet (including the padding byte), then it will ignore that
+packet. If either @ref{Noise, noise}, or @ref{CPR} are enabled, then all
+outgoing packets are filled up to that MTU value.
 
-Underlying TAP interface has lower MTU value -- 42 bytes smaller: 26
-bytes overhead on transport message and 14 bytes for Ethernet frame.
-Client and server will print what MTU value should be used on TAP
-interface.
+Default MTU equals to 1514 bytes (1500 bytes of Ethernet payload, 14
+bytes of Ethernet header).
index 7139ab3db45f30a0f0e3e306f88d637575e004c8..b785be21e8c31f38d8c35127329cb63cd32d796c 100644 (file)
@@ -1,8 +1,8 @@
 @node Server
 @section Server part
 
-Except for common @code{-mtu}, @code{-stats}, @code{-egd} options server
-has the following ones:
+Except for common @code{-stats}, @code{-egd} options server has the
+following ones:
 
 @table @code
 
@@ -27,6 +27,7 @@ Configuration file is JSON file with following example structure:
 {
   "stargrave": {                        <-- Peer human readable name
     "iface": "tap10",                   <-- OPTIONAL TAP interface name
+    "mtu": 1514,                        <-- OPTIONAL overriden MTU
     "up": "./stargrave-up.sh",          <-- OPTIONAL up-script
     "down": "./stargrave-down.sh",      <-- OPTIONAL down-script
     "timeout": 60,                      <-- OPTIONAL overriden timeout
index 9b5bf1891ad6fa00f110c5dec8987bd0c8046a78..630547d82bfae1261be00f6ccca29a071800a3c5 100644 (file)
@@ -41,7 +41,7 @@ var (
        stats       = flag.String("stats", "", "Enable stats retrieving on host:port")
        proxyAddr   = flag.String("proxy", "", "Use HTTP proxy on host:port")
        proxyAuth   = flag.String("proxy-auth", "", "user:password Basic proxy auth")
-       mtu         = flag.Int("mtu", 1452, "MTU for outgoing packets")
+       mtu         = flag.Int("mtu", govpn.MTUDefault, "MTU of TAP interface")
        timeoutP    = flag.Int("timeout", 60, "Timeout seconds")
        noisy       = flag.Bool("noise", false, "Enable noise appending")
        encless     = flag.Bool("encless", false, "Encryptionless mode")
@@ -62,8 +62,6 @@ func main() {
        var err error
        log.SetFlags(log.Ldate | log.Lmicroseconds | log.Lshortfile)
 
-       govpn.MTU = *mtu
-
        if *egdPath != "" {
                log.Println("Using", *egdPath, "EGD")
                govpn.EGDInit(*egdPath)
@@ -83,6 +81,7 @@ func main() {
        conf = &govpn.PeerConf{
                Id:       verifier.Id,
                Iface:    *ifaceName,
+               MTU:      *mtu,
                Timeout:  time.Second * time.Duration(timeout),
                Noise:    *noisy,
                CPR:      *cpr,
@@ -93,12 +92,11 @@ func main() {
        idsCache = govpn.NewCipherCache([]govpn.PeerId{*verifier.Id})
        log.Println(govpn.VersionGet())
 
-       tap, err = govpn.TAPListen(*ifaceName)
+       tap, err = govpn.TAPListen(*ifaceName, *mtu)
        if err != nil {
                log.Fatalln("Can not listen on TAP interface:", err)
        }
 
-       log.Println("Max MTU on TAP interface:", govpn.TAPMaxMTU())
        if *stats != "" {
                log.Println("Stats are going to listen on", *stats)
                statsPort, err := net.Listen("tcp", *stats)
index 7f3c172105ce0bf709ff15cbee4e549c55a4bca0..88ddeeb2226c4dd4856a4db1b021dee87776303d 100644 (file)
@@ -43,7 +43,7 @@ func startTCP(timeouted, rehandshaking, termination chan struct{}) {
 
 func handleTCP(conn *net.TCPConn, timeouted, rehandshaking, termination chan struct{}) {
        hs := govpn.HandshakeStart(*remoteAddr, conn, conf)
-       buf := make([]byte, 2*(govpn.EncLessEnlargeSize+govpn.MTU)+govpn.MTU)
+       buf := make([]byte, 2*(govpn.EncLessEnlargeSize+*mtu)+*mtu)
        var n int
        var err error
        var prev int
index 8e8ecf97d18bda7d3c2e0ebe57fdfd5a8ce84468..581e66cf74f122ceee169a53c86f1dab0f6b6dc3 100644 (file)
@@ -39,7 +39,7 @@ func startUDP(timeouted, rehandshaking, termination chan struct{}) {
        log.Println("Connected to UDP:" + *remoteAddr)
 
        hs := govpn.HandshakeStart(*remoteAddr, conn, conf)
-       buf := make([]byte, govpn.MTU)
+       buf := make([]byte, *mtu*2)
        var n int
        var timeouts int
        var peer *govpn.Peer
index 284f4f9dc5a2047b0cefed8c5f6d6e1728f15ad1..809c56d8c9453e4678b97ad49e32db0cf5c337fa 100644 (file)
@@ -56,11 +56,15 @@ func confRead() map[govpn.PeerId]*govpn.PeerConf {
                if pc.EncLess {
                        pc.Noise = true
                }
+               if pc.MTU == 0 {
+                       pc.MTU = govpn.MTUDefault
+               }
                conf := govpn.PeerConf{
                        Verifier: verifier,
                        Id:       verifier.Id,
                        Name:     name,
                        Iface:    pc.Iface,
+                       MTU:      pc.MTU,
                        Up:       pc.Up,
                        Down:     pc.Down,
                        Noise:    pc.Noise,
index d9de06a2c6b24f0550872f729f299e89b9439415..9a73b25da3acb78a2832182d175750c53c97c340 100644 (file)
@@ -36,7 +36,6 @@ var (
        confPath = flag.String("conf", "peers.json", "Path to configuration JSON")
        stats    = flag.String("stats", "", "Enable stats retrieving on host:port")
        proxy    = flag.String("proxy", "", "Enable HTTP proxy on host:port")
-       mtu      = flag.Int("mtu", 1452, "MTU for outgoing packets")
        egdPath  = flag.String("egd", "", "Optional path to EGD socket")
 )
 
@@ -46,7 +45,6 @@ func main() {
        log.SetFlags(log.Ldate | log.Lmicroseconds | log.Lshortfile)
        log.Println(govpn.VersionGet())
 
-       govpn.MTU = *mtu
        confInit()
        knownPeers = govpn.KnownPeers(make(map[string]**govpn.Peer))
 
@@ -73,7 +71,6 @@ func main() {
        hsHeartbeat := time.Tick(timeout)
        go func() { <-hsHeartbeat }()
 
-       log.Println("Max MTU on TAP interface:", govpn.TAPMaxMTU())
        if *stats != "" {
                log.Println("Stats are going to listen on", *stats)
                statsPort, err := net.Listen("tcp", *stats)
index 1739a879289b323c8a90e8515d10ed446ffd676a..c0e7f16f784ff0bf1a80d819bd41465bce74dddd 100644 (file)
@@ -51,7 +51,7 @@ func startTCP() {
 
 func handleTCP(conn net.Conn) {
        addr := conn.RemoteAddr().String()
-       buf := make([]byte, govpn.EncLessEnlargeSize+2*govpn.MTU)
+       buf := make([]byte, govpn.EncLessEnlargeSize+2*govpn.MTUMax)
        var n int
        var err error
        var prev int
@@ -120,7 +120,7 @@ func handleTCP(conn net.Conn) {
                                peer = nil
                                break
                        }
-                       tap, err = govpn.TAPListen(ifaceName)
+                       tap, err = govpn.TAPListen(ifaceName, peer.MTU)
                        if err != nil {
                                log.Println("Unable to create TAP:", err)
                                peer = nil
index e05f44d96e71011d7d49ac09618e25d35686104d..ddbbee81e660251903ec45496f737f02e68a9d80 100644 (file)
@@ -50,7 +50,7 @@ func startUDP() {
        }
        log.Println("Listening on UDP:" + *bindAddr)
 
-       udpBufs <- make([]byte, govpn.MTU)
+       udpBufs <- make([]byte, govpn.MTUMax)
        go func() {
                var buf []byte
                var raddr *net.UDPAddr
@@ -103,8 +103,8 @@ func startUDP() {
                        hsLock.Unlock()
 
                        go func() {
-                               udpBufs <- make([]byte, govpn.MTU)
-                               udpBufs <- make([]byte, govpn.MTU)
+                               udpBufs <- make([]byte, govpn.MTUMax)
+                               udpBufs <- make([]byte, govpn.MTUMax)
                        }()
                        peersByIdLock.RLock()
                        addrPrev, exists = peersById[*peer.Id]
@@ -139,7 +139,7 @@ func startUDP() {
                                        if err != nil {
                                                return
                                        }
-                                       tap, err := govpn.TAPListen(ifaceName)
+                                       tap, err := govpn.TAPListen(ifaceName, peer.MTU)
                                        if err != nil {
                                                log.Println("Unable to create TAP:", err)
                                                return
index e1bd28ce9c88af2f1e98a6e1fa8dd6f5b2767826..b453ed9be791a0295b49b5dadbee15cab1754bb5 100644 (file)
@@ -28,10 +28,11 @@ import (
 
 const (
        TimeoutDefault = 60
+       MTUMax         = 9000
+       MTUDefault     = 1500 + 14
 )
 
 var (
-       MTU     int
        Version string
 )
 
@@ -68,5 +69,5 @@ func cprCycleCalculate(rate int) time.Duration {
        if rate == 0 {
                return time.Duration(0)
        }
-       return time.Second / time.Duration(rate*(1<<10)/MTU)
+       return time.Second / time.Duration(rate*(1<<10)/MTUMax)
 }
index eb69ec6d1de34b34dbe19e776cca5197e5613436..2d3937d7d0c7fa217b0b4332261297c9ef3abe85 100644 (file)
@@ -28,6 +28,7 @@ type PeerConf struct {
        Id          *PeerId       `json:"-"`
        Name        string        `json:"name"`
        Iface       string        `json:"iface"`
+       MTU         int           `json:"mtu"`
        Up          string        `json:"up"`
        Down        string        `json:"down"`
        TimeoutInt  int           `json:"timeout"`
index 6c5633c1a59db437bc943ee0ca00afece779b3cb..fb0c649d168b2d8d045158a14db3e9e755b1afbc 100644 (file)
@@ -161,7 +161,7 @@ func HandshakeStart(addr string, conn io.Writer, conf *PeerConf) *Handshake {
        }
        var enc []byte
        if conf.Noise {
-               enc = make([]byte, MTU-xtea.BlockSize-RSize)
+               enc = make([]byte, conf.MTU-xtea.BlockSize-RSize)
        } else {
                enc = make([]byte, 32)
        }
@@ -189,7 +189,7 @@ func HandshakeStart(addr string, conn io.Writer, conf *PeerConf) *Handshake {
 func (h *Handshake) Server(data []byte) *Peer {
        // R + ENC(H(DSAPub), R, El(CDHPub)) + IDtag
        if h.rNonce == nil && ((!h.Conf.EncLess && len(data) >= 48) ||
-               (h.Conf.EncLess && len(data) == EncLessEnlargeSize+MTU)) {
+               (h.Conf.EncLess && len(data) == EncLessEnlargeSize+h.Conf.MTU)) {
                h.rNonce = new([RSize]byte)
                copy(h.rNonce[:], data[:RSize])
 
@@ -227,7 +227,7 @@ func (h *Handshake) Server(data []byte) *Peer {
                var encPub []byte
                var err error
                if h.Conf.EncLess {
-                       encPub = make([]byte, MTU)
+                       encPub = make([]byte, h.Conf.MTU)
                        copy(encPub, dhPubRepr[:])
                        encPub, err = EncLessEncode(h.dsaPubH, h.rNonceNext(1), encPub)
                        if err != nil {
@@ -249,9 +249,9 @@ func (h *Handshake) Server(data []byte) *Peer {
                }
                var encRs []byte
                if h.Conf.Noise && !h.Conf.EncLess {
-                       encRs = make([]byte, MTU-len(encPub)-xtea.BlockSize)
+                       encRs = make([]byte, h.Conf.MTU-len(encPub)-xtea.BlockSize)
                } else if h.Conf.EncLess {
-                       encRs = make([]byte, MTU-xtea.BlockSize)
+                       encRs = make([]byte, h.Conf.MTU-xtea.BlockSize)
                } else {
                        encRs = make([]byte, RSize+SSize)
                }
@@ -271,7 +271,7 @@ func (h *Handshake) Server(data []byte) *Peer {
        } else
        // ENC(K, R+1, RS + RC + SC + Sign(DSAPriv, K)) + IDtag
        if h.rClient == nil && ((!h.Conf.EncLess && len(data) >= 120) ||
-               (h.Conf.EncLess && len(data) == EncLessEnlargeSize+MTU)) {
+               (h.Conf.EncLess && len(data) == EncLessEnlargeSize+h.Conf.MTU)) {
                var dec []byte
                var err error
                if h.Conf.EncLess {
@@ -308,7 +308,7 @@ func (h *Handshake) Server(data []byte) *Peer {
                // Send final answer to client
                var enc []byte
                if h.Conf.Noise {
-                       enc = make([]byte, MTU-xtea.BlockSize)
+                       enc = make([]byte, h.Conf.MTU-xtea.BlockSize)
                } else {
                        enc = make([]byte, RSize)
                }
@@ -347,7 +347,7 @@ func (h *Handshake) Client(data []byte) *Peer {
        // ENC(H(DSAPub), R+1, El(SDHPub)) + ENC(K, R, RS + SS) + IDtag
        if h.rServer == nil && h.key == nil &&
                ((!h.Conf.EncLess && len(data) >= 80) ||
-                       (h.Conf.EncLess && len(data) == 2*(EncLessEnlargeSize+MTU))) {
+                       (h.Conf.EncLess && len(data) == 2*(EncLessEnlargeSize+h.Conf.MTU))) {
                // Decrypt remote public key
                sDHRepr := new([32]byte)
                var tmp []byte
@@ -417,7 +417,7 @@ func (h *Handshake) Client(data []byte) *Peer {
 
                var enc []byte
                if h.Conf.Noise {
-                       enc = make([]byte, MTU-xtea.BlockSize)
+                       enc = make([]byte, h.Conf.MTU-xtea.BlockSize)
                } else {
                        enc = make([]byte, RSize+RSize+SSize+ed25519.SignatureSize)
                }
@@ -440,7 +440,7 @@ func (h *Handshake) Client(data []byte) *Peer {
        } else
        // ENC(K, R+2, RC) + IDtag
        if h.key != nil && ((!h.Conf.EncLess && len(data) >= 16) ||
-               (h.Conf.EncLess && len(data) == EncLessEnlargeSize+MTU)) {
+               (h.Conf.EncLess && len(data) == EncLessEnlargeSize+h.Conf.MTU)) {
                var err error
                // Decrypt rClient
                var dec []byte
index f3bb0b43befea0c5081fc9dfb994be8415b8a532..58dbc715080d0e1774439a20d0251ee10a0d71e9 100644 (file)
@@ -22,6 +22,7 @@ import (
        "bytes"
        "encoding/binary"
        "io"
+       "log"
        "sync"
        "sync/atomic"
        "time"
@@ -72,6 +73,7 @@ type Peer struct {
        CPR         int
        CPRCycle    time.Duration `json:"-"`
        EncLess     bool
+       MTU         int
 
        // Cryptography related
        Key          *[SSize]byte `json:"-"`
@@ -156,7 +158,7 @@ func newPeer(isClient bool, addr string, conn io.Writer, conf *PeerConf, key *[S
                timeout = timeout / TimeoutHeartbeat
        }
 
-       bufSize := S20BS + MTU + NonceSize
+       bufSize := S20BS + 2*conf.MTU
        if conf.EncLess {
                bufSize += EncLessEnlargeSize
                noiseEnable = true
@@ -170,6 +172,7 @@ func newPeer(isClient bool, addr string, conn io.Writer, conf *PeerConf, key *[S
                CPR:         conf.CPR,
                CPRCycle:    cprCycle,
                EncLess:     conf.EncLess,
+               MTU:         conf.MTU,
 
                Key:          key,
                NonceCipher:  newNonceCipher(key),
@@ -203,6 +206,10 @@ func newPeer(isClient bool, addr string, conn io.Writer, conf *PeerConf, key *[S
 // that he is free to receive new packets. Encrypted and authenticated
 // packets will be sent to remote Peer side immediately.
 func (p *Peer) EthProcess(data []byte) {
+       if len(data) > p.MTU-1 { // 1 is for padding byte
+               log.Println("Padded data packet size", len(data)+1, "is bigger than MTU", p.MTU, p)
+               return
+       }
        p.now = time.Now()
        p.BusyT.Lock()
 
@@ -225,9 +232,9 @@ func (p *Peer) EthProcess(data []byte) {
        }
 
        if p.NoiseEnable && !p.EncLess {
-               p.frameT = p.bufT[S20BS : S20BS+MTU-TagSize]
+               p.frameT = p.bufT[S20BS : S20BS+p.MTU-TagSize]
        } else if p.EncLess {
-               p.frameT = p.bufT[S20BS : S20BS+MTU]
+               p.frameT = p.bufT[S20BS : S20BS+p.MTU]
        } else {
                p.frameT = p.bufT[S20BS : S20BS+len(data)+1+NonceSize]
        }
index 40f6b1d4970210c8e6d0ccd45d4a2629ac24110d..d0526085fa809884d0a11815530418ae6e532279 100644 (file)
@@ -44,14 +44,12 @@ func (d Dummy) Write(b []byte) (int, error) {
 }
 
 func init() {
-       MTU = 1500
        id := new([IDSize]byte)
        peerId := PeerId(*id)
        conf = &PeerConf{
                Id:      &peerId,
+               MTU:     MTUDefault,
                Timeout: time.Second * time.Duration(TimeoutDefault),
-               Noise:   false,
-               CPR:     0,
        }
        peer = newPeer(true, "foo", Dummy{&ciphertext}, conf, new([SSize]byte))
        plaintext = make([]byte, 789)
index 43207c19e7cc032771d05eb27c40453fd4a4de13..6e545b4decfeae9262a73f82e00348e60c89c609 100644 (file)
@@ -20,12 +20,6 @@ package govpn
 
 import (
        "io"
-
-       "golang.org/x/crypto/poly1305"
-)
-
-const (
-       EtherSize = 14
 )
 
 type TAP struct {
@@ -41,14 +35,7 @@ var (
        taps = make(map[string]*TAP)
 )
 
-// Return maximal acceptable TAP interface MTU. This is daemon's MTU
-// minus nonce, MAC, pad and Ethernet header sizes.
-func TAPMaxMTU() int {
-       return MTU - poly1305.TagSize - NonceSize - 1 - EtherSize
-}
-
-func NewTAP(ifaceName string) (*TAP, error) {
-       maxIfacePktSize := TAPMaxMTU() + EtherSize
+func NewTAP(ifaceName string, mtu int) (*TAP, error) {
        tapRaw, err := newTAPer(ifaceName)
        if err != nil {
                return nil, err
@@ -56,8 +43,8 @@ func NewTAP(ifaceName string) (*TAP, error) {
        tap := TAP{
                Name: ifaceName,
                dev:  tapRaw,
-               buf0: make([]byte, maxIfacePktSize),
-               buf1: make([]byte, maxIfacePktSize),
+               buf0: make([]byte, mtu),
+               buf1: make([]byte, mtu),
                Sink: make(chan []byte),
        }
        go func() {
@@ -85,12 +72,12 @@ func (t *TAP) Write(data []byte) (n int, err error) {
        return t.dev.Write(data)
 }
 
-func TAPListen(ifaceName string) (*TAP, error) {
+func TAPListen(ifaceName string, mtu int) (*TAP, error) {
        tap, exists := taps[ifaceName]
        if exists {
                return tap, nil
        }
-       tap, err := NewTAP(ifaceName)
+       tap, err := NewTAP(ifaceName, mtu)
        if err != nil {
                return nil, err
        }