mirror of
https://github.com/tladesignz/dnstt.git
synced 2026-09-29 10:28:00 +03:00
Larger downstream capacity.
This commit is contained in:
+38
-33
@@ -23,6 +23,28 @@ import (
|
||||
const (
|
||||
idleTimeout = 10 * time.Minute
|
||||
responseTTL = 60
|
||||
|
||||
// We don't send UDP payloads larger than this, in an attempt to avoid
|
||||
// network-layer fragmentation. 40 bytes is the size of an IPv6 header
|
||||
// (though without any extension headers). 8 bytes is the size of a UDP
|
||||
// header.
|
||||
maxUDPPayload = 1500 - 40 - 8
|
||||
|
||||
// We may have a variable amount of room in which to encode downstream
|
||||
// packets in each response, because we must echo the query's Question
|
||||
// section, which is of variable length. But we cannot give dynamic
|
||||
// packet size limits to KCP; the best we can do is set a global maximum
|
||||
// which no packet will exceed. We choose that maximum to keep the UDP
|
||||
// payload size under maxUDPPayload, even in the worst case of a
|
||||
// maximum-length name in the Question section. The precise limit is
|
||||
// 1153 = (maxUDPPayload - 294) * 255/256, where 294 is the size of a
|
||||
// DNS message containing a Question section with a name that is 255
|
||||
// bytes long, an Answer section with a single TXT RR whose name is a
|
||||
// compressed pointer to the name in the Question section and no data,
|
||||
// and an Additional section with an OPT RR for EDNS(0); and 255/256
|
||||
// reflects the overhead of encoding data into a TXT RR. We leave some
|
||||
// slack in case of IPv6 extension headers or non-Ethernet links.
|
||||
maxEncodedPayload = 1100
|
||||
)
|
||||
|
||||
// A base32 encoding without padding.
|
||||
@@ -110,23 +132,11 @@ func acceptSessions(ln *kcp.Listener, upstream *net.TCPAddr) error {
|
||||
0, // default resend
|
||||
1, // nc=1 => congestion window off
|
||||
)
|
||||
// Set the maximum transmission unit.
|
||||
longName, err := dns.NewName([][]byte{
|
||||
bytes.Repeat([]byte{'a'}, 63),
|
||||
bytes.Repeat([]byte{'b'}, 63),
|
||||
bytes.Repeat([]byte{'c'}, 63),
|
||||
bytes.Repeat([]byte{'d'}, 61),
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
// Set the maximum transmission unit. 2 bytes accounts for a
|
||||
// packet length prefix.
|
||||
if rc := conn.SetMtu(maxEncodedPayload - 2); !rc {
|
||||
panic(rc)
|
||||
}
|
||||
mtu := dnsMessageCapacity(longName)
|
||||
if mtu < 80 {
|
||||
// This value doesn't depend on any configuration values, so it
|
||||
// should never be too small.
|
||||
panic("too little space for downstream payload")
|
||||
}
|
||||
conn.SetMtu(mtu)
|
||||
go func() {
|
||||
defer conn.Close()
|
||||
err := acceptStreams(conn, upstream)
|
||||
@@ -137,22 +147,6 @@ func acceptSessions(ln *kcp.Listener, upstream *net.TCPAddr) error {
|
||||
}
|
||||
}
|
||||
|
||||
func dnsMessageCapacity(name dns.Name) int {
|
||||
message := dns.Message{
|
||||
Question: []dns.Question{
|
||||
dns.Question{Name: name},
|
||||
},
|
||||
Answer: []dns.RR{
|
||||
dns.RR{Name: name},
|
||||
},
|
||||
}
|
||||
builder, err := message.WireFormat()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return (512 - len(builder)) * 255 / 256
|
||||
}
|
||||
|
||||
func nextPacket(r *bytes.Reader) ([]byte, error) {
|
||||
eof := func(err error) error {
|
||||
if err == io.EOF {
|
||||
@@ -240,6 +234,17 @@ func responseFor(query *dns.Message, domain dns.Name) (*dns.Message, turbotunnel
|
||||
payloadSize = 512
|
||||
}
|
||||
}
|
||||
if payloadSize < maxUDPPayload {
|
||||
// We require clients to support EDNS(0) with a minimum payload
|
||||
// size; otherwise we would have to set a small KCP MTU (only
|
||||
// around 200 bytes).
|
||||
// https://tools.ietf.org/html/rfc6891#section-7
|
||||
// "If there is a problem with processing the OPT record itself,
|
||||
// such as an option value that is badly formatted or that
|
||||
// includes out-of-range values, a FORMERR MUST be returned."
|
||||
resp.Flags |= dns.RcodeFormatError
|
||||
return resp, clientID, nil
|
||||
}
|
||||
|
||||
if query.Flags&0x7800 != 0 {
|
||||
// We don't support OPCODE != QUERY.
|
||||
@@ -381,7 +386,7 @@ func sendLoop(dnsConn net.PacketConn, ttConn *turbotunnel.QueuePacketConn, ch <-
|
||||
|
||||
var payload bytes.Buffer
|
||||
|
||||
limit := dnsMessageCapacity(rec.Resp.Question[0].Name)
|
||||
limit := maxEncodedPayload
|
||||
if len(nextP) > 0 {
|
||||
// No length check on any packet left over from
|
||||
// the previous bundle -- if it's too large, we
|
||||
|
||||
Reference in New Issue
Block a user