mirror of
https://git.zx2c4.com/wireguard-go
synced 2024-11-15 01:05:15 +01:00
send: propagate DSCP bits to the outer tunnel
Like many, I am using WiFi a lot and often on congested networks. Without this, Wireguard strips the DSCP bits, preventing WME from kicking in and improving the audio/video experience. Yes, it's technically an information leak. Who cares? It's not like if traffic analysis based on packet sizes or timings wasn't a thing. This is the first patch of the serie, more work has to happen on ECN Signed-off-by: Florent Daigniere <nextgens@freenetproject.org>
This commit is contained in:
parent
42c6d0e261
commit
9e686cd714
2
conn.go
2
conn.go
@ -22,7 +22,7 @@ type Bind interface {
|
|||||||
SetMark(value uint32) error
|
SetMark(value uint32) error
|
||||||
ReceiveIPv6(buff []byte) (int, Endpoint, error)
|
ReceiveIPv6(buff []byte) (int, Endpoint, error)
|
||||||
ReceiveIPv4(buff []byte) (int, Endpoint, error)
|
ReceiveIPv4(buff []byte) (int, Endpoint, error)
|
||||||
Send(buff []byte, end Endpoint) error
|
Send(buff []byte, end Endpoint, tos byte) error
|
||||||
Close() error
|
Close() error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,18 +258,18 @@ func (bind *NativeBind) ReceiveIPv4(buff []byte) (int, Endpoint, error) {
|
|||||||
return n, &end, err
|
return n, &end, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bind *NativeBind) Send(buff []byte, end Endpoint) error {
|
func (bind *NativeBind) Send(buff []byte, end Endpoint, tos byte) error {
|
||||||
nend := end.(*NativeEndpoint)
|
nend := end.(*NativeEndpoint)
|
||||||
if !nend.isV6 {
|
if !nend.isV6 {
|
||||||
if bind.sock4 == -1 {
|
if bind.sock4 == -1 {
|
||||||
return syscall.EAFNOSUPPORT
|
return syscall.EAFNOSUPPORT
|
||||||
}
|
}
|
||||||
return send4(bind.sock4, nend, buff)
|
return send4(bind.sock4, nend, buff, tos)
|
||||||
} else {
|
} else {
|
||||||
if bind.sock6 == -1 {
|
if bind.sock6 == -1 {
|
||||||
return syscall.EAFNOSUPPORT
|
return syscall.EAFNOSUPPORT
|
||||||
}
|
}
|
||||||
return send6(bind.sock6, nend, buff)
|
return send6(bind.sock6, nend, buff, tos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -452,13 +452,18 @@ func create6(port uint16) (int, uint16, error) {
|
|||||||
return fd, uint16(addr.Port), err
|
return fd, uint16(addr.Port), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func send4(sock int, end *NativeEndpoint, buff []byte) error {
|
func send4(sock int, end *NativeEndpoint, buff []byte, tos byte) error {
|
||||||
|
|
||||||
// construct message header
|
// construct message header
|
||||||
|
type ipTos struct {
|
||||||
|
tos byte
|
||||||
|
}
|
||||||
|
|
||||||
cmsg := struct {
|
cmsg := struct {
|
||||||
cmsghdr unix.Cmsghdr
|
cmsghdr unix.Cmsghdr
|
||||||
pktinfo unix.Inet4Pktinfo
|
pktinfo unix.Inet4Pktinfo
|
||||||
|
cmsghdr2 unix.Cmsghdr
|
||||||
|
iptos ipTos
|
||||||
}{
|
}{
|
||||||
unix.Cmsghdr{
|
unix.Cmsghdr{
|
||||||
Level: unix.IPPROTO_IP,
|
Level: unix.IPPROTO_IP,
|
||||||
@ -469,6 +474,15 @@ func send4(sock int, end *NativeEndpoint, buff []byte) error {
|
|||||||
Spec_dst: end.src4().src,
|
Spec_dst: end.src4().src,
|
||||||
Ifindex: end.src4().ifindex,
|
Ifindex: end.src4().ifindex,
|
||||||
},
|
},
|
||||||
|
unix.Cmsghdr{
|
||||||
|
Level: unix.IPPROTO_IP,
|
||||||
|
Type: unix.IP_TOS,
|
||||||
|
Len: 1 + unix.SizeofCmsghdr,
|
||||||
|
},
|
||||||
|
ipTos{
|
||||||
|
tos: tos,
|
||||||
|
},
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := unix.SendmsgN(sock, buff, (*[unsafe.Sizeof(cmsg)]byte)(unsafe.Pointer(&cmsg))[:], end.dst4(), 0)
|
_, err := unix.SendmsgN(sock, buff, (*[unsafe.Sizeof(cmsg)]byte)(unsafe.Pointer(&cmsg))[:], end.dst4(), 0)
|
||||||
@ -488,13 +502,18 @@ func send4(sock int, end *NativeEndpoint, buff []byte) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func send6(sock int, end *NativeEndpoint, buff []byte) error {
|
func send6(sock int, end *NativeEndpoint, buff []byte, tos byte) error {
|
||||||
|
|
||||||
// construct message header
|
// construct message header
|
||||||
|
type ipTos struct {
|
||||||
|
tos byte
|
||||||
|
}
|
||||||
|
|
||||||
cmsg := struct {
|
cmsg := struct {
|
||||||
cmsghdr unix.Cmsghdr
|
cmsghdr unix.Cmsghdr
|
||||||
pktinfo unix.Inet6Pktinfo
|
pktinfo unix.Inet6Pktinfo
|
||||||
|
cmsghdr2 unix.Cmsghdr
|
||||||
|
tclass ipTos
|
||||||
}{
|
}{
|
||||||
unix.Cmsghdr{
|
unix.Cmsghdr{
|
||||||
Level: unix.IPPROTO_IPV6,
|
Level: unix.IPPROTO_IPV6,
|
||||||
@ -505,6 +524,14 @@ func send6(sock int, end *NativeEndpoint, buff []byte) error {
|
|||||||
Addr: end.src6().src,
|
Addr: end.src6().src,
|
||||||
Ifindex: end.dst6().ZoneId,
|
Ifindex: end.dst6().ZoneId,
|
||||||
},
|
},
|
||||||
|
unix.Cmsghdr{
|
||||||
|
Level: unix.IPPROTO_IPV6,
|
||||||
|
Type: unix.IPV6_TCLASS,
|
||||||
|
Len: 1 + unix.SizeofCmsghdr,
|
||||||
|
},
|
||||||
|
ipTos{
|
||||||
|
tos: tos,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if cmsg.pktinfo.Addr == [16]byte{} {
|
if cmsg.pktinfo.Addr == [16]byte{} {
|
||||||
|
4
peer.go
4
peer.go
@ -125,7 +125,7 @@ func (device *Device) NewPeer(pk NoisePublicKey) (*Peer, error) {
|
|||||||
return peer, nil
|
return peer, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (peer *Peer) SendBuffer(buffer []byte) error {
|
func (peer *Peer) SendBuffer(buffer []byte, tos byte) error {
|
||||||
peer.device.net.RLock()
|
peer.device.net.RLock()
|
||||||
defer peer.device.net.RUnlock()
|
defer peer.device.net.RUnlock()
|
||||||
|
|
||||||
@ -140,7 +140,7 @@ func (peer *Peer) SendBuffer(buffer []byte) error {
|
|||||||
return errors.New("no known endpoint for peer")
|
return errors.New("no known endpoint for peer")
|
||||||
}
|
}
|
||||||
|
|
||||||
return peer.device.net.bind.Send(buffer, peer.endpoint)
|
return peer.device.net.bind.Send(buffer, peer.endpoint, tos)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (peer *Peer) String() string {
|
func (peer *Peer) String() string {
|
||||||
|
17
send.go
17
send.go
@ -41,6 +41,10 @@ import (
|
|||||||
* (to allow the construction of transport messages in-place)
|
* (to allow the construction of transport messages in-place)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
const (
|
||||||
|
HandshakeDSCP = 0x88 // AF41, plus 00 ECN
|
||||||
|
)
|
||||||
|
|
||||||
type QueueOutboundElement struct {
|
type QueueOutboundElement struct {
|
||||||
dropped int32
|
dropped int32
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
@ -49,6 +53,7 @@ type QueueOutboundElement struct {
|
|||||||
nonce uint64 // nonce for encryption
|
nonce uint64 // nonce for encryption
|
||||||
keypair *Keypair // keypair for encryption
|
keypair *Keypair // keypair for encryption
|
||||||
peer *Peer // related peer
|
peer *Peer // related peer
|
||||||
|
tos byte // Type of Service (DSCP + ECN bits)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (device *Device) NewOutboundElement() *QueueOutboundElement {
|
func (device *Device) NewOutboundElement() *QueueOutboundElement {
|
||||||
@ -159,7 +164,7 @@ func (peer *Peer) SendHandshakeInitiation(isRetry bool) error {
|
|||||||
peer.timersAnyAuthenticatedPacketTraversal()
|
peer.timersAnyAuthenticatedPacketTraversal()
|
||||||
peer.timersAnyAuthenticatedPacketSent()
|
peer.timersAnyAuthenticatedPacketSent()
|
||||||
|
|
||||||
err = peer.SendBuffer(packet)
|
err = peer.SendBuffer(packet, HandshakeDSCP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
peer.device.log.Error.Println(peer, "- Failed to send handshake initiation", err)
|
peer.device.log.Error.Println(peer, "- Failed to send handshake initiation", err)
|
||||||
}
|
}
|
||||||
@ -197,7 +202,7 @@ func (peer *Peer) SendHandshakeResponse() error {
|
|||||||
peer.timersAnyAuthenticatedPacketTraversal()
|
peer.timersAnyAuthenticatedPacketTraversal()
|
||||||
peer.timersAnyAuthenticatedPacketSent()
|
peer.timersAnyAuthenticatedPacketSent()
|
||||||
|
|
||||||
err = peer.SendBuffer(packet)
|
err = peer.SendBuffer(packet, HandshakeDSCP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
peer.device.log.Error.Println(peer, "- Failed to send handshake response", err)
|
peer.device.log.Error.Println(peer, "- Failed to send handshake response", err)
|
||||||
}
|
}
|
||||||
@ -218,7 +223,7 @@ func (device *Device) SendHandshakeCookie(initiatingElem *QueueHandshakeElement)
|
|||||||
var buff [MessageCookieReplySize]byte
|
var buff [MessageCookieReplySize]byte
|
||||||
writer := bytes.NewBuffer(buff[:0])
|
writer := bytes.NewBuffer(buff[:0])
|
||||||
binary.Write(writer, binary.LittleEndian, reply)
|
binary.Write(writer, binary.LittleEndian, reply)
|
||||||
device.net.bind.Send(writer.Bytes(), initiatingElem.endpoint)
|
device.net.bind.Send(writer.Bytes(), initiatingElem.endpoint, HandshakeDSCP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
device.log.Error.Println("Failed to send cookie reply:", err)
|
device.log.Error.Println("Failed to send cookie reply:", err)
|
||||||
}
|
}
|
||||||
@ -294,14 +299,14 @@ func (device *Device) RoutineReadFromTUN() {
|
|||||||
}
|
}
|
||||||
dst := elem.packet[IPv4offsetDst : IPv4offsetDst+net.IPv4len]
|
dst := elem.packet[IPv4offsetDst : IPv4offsetDst+net.IPv4len]
|
||||||
peer = device.allowedips.LookupIPv4(dst)
|
peer = device.allowedips.LookupIPv4(dst)
|
||||||
|
elem.tos = elem.packet[1];
|
||||||
case ipv6.Version:
|
case ipv6.Version:
|
||||||
if len(elem.packet) < ipv6.HeaderLen {
|
if len(elem.packet) < ipv6.HeaderLen {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
dst := elem.packet[IPv6offsetDst : IPv6offsetDst+net.IPv6len]
|
dst := elem.packet[IPv6offsetDst : IPv6offsetDst+net.IPv6len]
|
||||||
peer = device.allowedips.LookupIPv6(dst)
|
peer = device.allowedips.LookupIPv6(dst)
|
||||||
|
elem.tos = elem.packet[1];
|
||||||
default:
|
default:
|
||||||
logDebug.Println("Received packet with unknown IP version")
|
logDebug.Println("Received packet with unknown IP version")
|
||||||
}
|
}
|
||||||
@ -600,7 +605,7 @@ func (peer *Peer) RoutineSequentialSender() {
|
|||||||
// send message and return buffer to pool
|
// send message and return buffer to pool
|
||||||
|
|
||||||
length := uint64(len(elem.packet))
|
length := uint64(len(elem.packet))
|
||||||
err := peer.SendBuffer(elem.packet)
|
err := peer.SendBuffer(elem.packet, elem.tos)
|
||||||
device.PutMessageBuffer(elem.buffer)
|
device.PutMessageBuffer(elem.buffer)
|
||||||
device.PutOutboundElement(elem)
|
device.PutOutboundElement(elem)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user