mirror of
https://github.com/tladesignz/dnstt.git
synced 2026-09-22 23:07:59 +03:00
Merge remote-tracking branch 'upstream/master'
# Conflicts: # dnstt-client/lib/dns.go # dnstt-server/main.go
This commit is contained in:
@@ -1,3 +1,24 @@
|
||||
## v1.20260501.0
|
||||
|
||||
Fixed an error in dnstt-server that could cause the server to stop
|
||||
processing traffic, while still running. Rarely, a sendto system call in
|
||||
the sendLoop function would cause sendLoop to return with an error.
|
||||
Meanwhile, recvLoop would keep running and processing incoming queries,
|
||||
but as sendLoop had finished, the server would cease to send back
|
||||
responses. In live testing, one possible cause of a sendto error was the
|
||||
Linux conntrack table becoming full from heavy traffic and the outgoing
|
||||
packet being blocked by a default DENY rule in the local firewall; other
|
||||
causes may have been possible. This release contains two changes to fix
|
||||
the problem: (1) sendto errors, other than net.ErrClosed, are now only
|
||||
logged and do not cause sendLoop to terminate; (2) if sendLoop (or any
|
||||
other top-level goroutine) does return, it causes the whole process to
|
||||
exit, which will make any failure noticeable and avoid the "running but
|
||||
not working" failure mode.
|
||||
|
||||
## v1.20241021.0
|
||||
|
||||
Added a CC0 COPYING file.
|
||||
|
||||
## v1.20240513.0
|
||||
|
||||
Updated utls to v1.6.6. Added a "random" fingerprint ID that maps to
|
||||
|
||||
@@ -239,6 +239,43 @@ tunnel-client$ curl --proxy socks5h://127.0.0.1:7000/ https://wtfismyip.com/text
|
||||
```
|
||||
|
||||
|
||||
### Dante SOCKS proxy
|
||||
|
||||
With the Dante SOCKS proxy (https://www.inet.no/dante/), a minimal
|
||||
configuration (/etc/danted.conf) may look like the following:
|
||||
|
||||
```
|
||||
internal: lo port = 8000
|
||||
external: eth0
|
||||
|
||||
clientmethod: none
|
||||
socksmethod: none
|
||||
|
||||
user.privileged: proxy
|
||||
user.unprivileged: nobody
|
||||
|
||||
client pass {
|
||||
from: lo to: 0/0
|
||||
}
|
||||
|
||||
socks block {
|
||||
from: 0.0.0.0/0 to: lo
|
||||
}
|
||||
|
||||
socks block {
|
||||
from: ::/0 to: lo
|
||||
}
|
||||
|
||||
socks pass {
|
||||
from: lo to: 0.0.0.0/0
|
||||
command: connect
|
||||
}
|
||||
```
|
||||
|
||||
See https://www.inet.no/dante/doc/latest/config/server.html for more
|
||||
examples.
|
||||
|
||||
|
||||
### Tor bridge
|
||||
|
||||
You can run a Tor bridge on the tunnel server and tunnel the connection
|
||||
|
||||
+6
-11
@@ -187,11 +187,6 @@ func (c *DNSPacketConn) recvLoop(transport net.PacketConn) error {
|
||||
var buf [4096]byte
|
||||
n, addr, err := transport.ReadFrom(buf[:])
|
||||
if err != nil {
|
||||
//goland:noinspection GoDeprecation
|
||||
if err, ok := err.(net.Error); ok && err.Temporary() {
|
||||
log.Printf("ReadFrom temporary error: %v", err)
|
||||
continue
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -257,29 +252,29 @@ func chunks(p []byte, n int) [][]byte {
|
||||
//
|
||||
// 0. Start with the raw packet contents.
|
||||
//
|
||||
// supercalifragilisticexpialidocious
|
||||
// supercalifragilisticexpialidocious
|
||||
//
|
||||
// 1. Length-prefix the packet and add random padding. A length prefix L < 0xe0
|
||||
// means a data packet of L bytes. A length prefix L ≥ 0xe0 means padding
|
||||
// of L − 0xe0 bytes (not counting the length of the length prefix itself).
|
||||
//
|
||||
// \xe3\xd9\xa3\x15\x22supercalifragilisticexpialidocious
|
||||
// \xe3\xd9\xa3\x15\x22supercalifragilisticexpialidocious
|
||||
//
|
||||
// 2. Prefix the ClientID.
|
||||
//
|
||||
// CLIENTID\xe3\xd9\xa3\x15\x22supercalifragilisticexpialidocious
|
||||
// CLIENTID\xe3\xd9\xa3\x15\x22supercalifragilisticexpialidocious
|
||||
//
|
||||
// 3. Base32-encode, without padding and in lower case.
|
||||
//
|
||||
// ingesrkokreujy6zumkse43vobsxey3bnruwm4tbm5uwy2ltoruwgzlyobuwc3djmrxwg2lpovzq
|
||||
// ingesrkokreujy6zumkse43vobsxey3bnruwm4tbm5uwy2ltoruwgzlyobuwc3djmrxwg2lpovzq
|
||||
//
|
||||
// 4. Break into labels of at most 63 octets.
|
||||
//
|
||||
// ingesrkokreujy6zumkse43vobsxey3bnruwm4tbm5uwy2ltoruwgzlyobuwc3d.jmrxwg2lpovzq
|
||||
// ingesrkokreujy6zumkse43vobsxey3bnruwm4tbm5uwy2ltoruwgzlyobuwc3d.jmrxwg2lpovzq
|
||||
//
|
||||
// 5. Append the domain.
|
||||
//
|
||||
// ingesrkokreujy6zumkse43vobsxey3bnruwm4tbm5uwy2ltoruwgzlyobuwc3d.jmrxwg2lpovzq.t.example.com
|
||||
// ingesrkokreujy6zumkse43vobsxey3bnruwm4tbm5uwy2ltoruwgzlyobuwc3d.jmrxwg2lpovzq.t.example.com
|
||||
func (c *DNSPacketConn) send(transport net.PacketConn, p []byte, addr net.Addr) error {
|
||||
var decoded []byte
|
||||
{
|
||||
|
||||
+40
-12
@@ -269,6 +269,7 @@ func acceptStreams(conn *kcp.UDPSession, privkey []byte, upstream string) error
|
||||
if err != nil {
|
||||
//goland:noinspection GoDeprecation
|
||||
if err, ok := err.(net.Error); ok && err.Temporary() {
|
||||
log.Printf("AcceptStream temporary error: %v", err)
|
||||
continue
|
||||
}
|
||||
return err
|
||||
@@ -295,6 +296,7 @@ func acceptSessions(ln *kcp.Listener, privkey []byte, mtu int, upstream string)
|
||||
if err != nil {
|
||||
//goland:noinspection GoDeprecation
|
||||
if err, ok := err.(net.Error); ok && err.Temporary() {
|
||||
log.Printf("AcceptKCP temporary error: %v", err)
|
||||
continue
|
||||
}
|
||||
return err
|
||||
@@ -516,11 +518,6 @@ func recvLoop(domain dns.Name, dnsConn net.PacketConn, ttConn *turbotunnel.Queue
|
||||
var buf [4096]byte
|
||||
n, addr, err := dnsConn.ReadFrom(buf[:])
|
||||
if err != nil {
|
||||
//goland:noinspection GoDeprecation
|
||||
if err, ok := err.(net.Error); ok && err.Temporary() {
|
||||
log.Printf("ReadFrom temporary error: %v", err)
|
||||
continue
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -606,6 +603,7 @@ func sendLoop(dnsConn net.PacketConn, ttConn *turbotunnel.QueuePacketConn, ch <-
|
||||
// overflow the capacity of the DNS response, we stash
|
||||
// to be bundled into a future response.
|
||||
timer := time.NewTimer(maxResponseDelay)
|
||||
timerExpired := false
|
||||
for {
|
||||
var p []byte
|
||||
unstash := ttConn.Unstash(rec.ClientID)
|
||||
@@ -626,6 +624,7 @@ func sendLoop(dnsConn net.PacketConn, ttConn *turbotunnel.QueuePacketConn, ch <-
|
||||
case p = <-unstash:
|
||||
case p = <-outgoing:
|
||||
case <-timer.C:
|
||||
timerExpired = true
|
||||
case nextRec = <-ch:
|
||||
}
|
||||
}
|
||||
@@ -634,7 +633,11 @@ func sendLoop(dnsConn net.PacketConn, ttConn *turbotunnel.QueuePacketConn, ch <-
|
||||
// only. The second and later packets must be
|
||||
// immediately available or they will be omitted
|
||||
// from this bundle.
|
||||
if !timerExpired && !timer.Stop() {
|
||||
<-timer.C
|
||||
}
|
||||
timer.Reset(0)
|
||||
timerExpired = false
|
||||
|
||||
if len(p) == 0 {
|
||||
// timer expired or receive on ch, we
|
||||
@@ -660,7 +663,9 @@ func sendLoop(dnsConn net.PacketConn, ttConn *turbotunnel.QueuePacketConn, ch <-
|
||||
_ = binary.Write(&payload, binary.BigEndian, uint16(len(p)))
|
||||
payload.Write(p)
|
||||
}
|
||||
timer.Stop()
|
||||
if !timerExpired && !timer.Stop() {
|
||||
<-timer.C
|
||||
}
|
||||
|
||||
rec.Resp.Answer[0].Data = dns.EncodeRDataTXT(payload.Bytes())
|
||||
}
|
||||
@@ -681,12 +686,14 @@ func sendLoop(dnsConn net.PacketConn, ttConn *turbotunnel.QueuePacketConn, ch <-
|
||||
// Now we actually send the message as a UDP packet.
|
||||
_, err = dnsConn.WriteTo(buf, rec.Addr)
|
||||
if err != nil {
|
||||
//goland:noinspection GoDeprecation
|
||||
if err, ok := err.(net.Error); ok && err.Temporary() {
|
||||
log.Printf("WriteTo temporary error: %v", err)
|
||||
continue
|
||||
// net.ErrClosed means we'll never be able to send on
|
||||
// dnsConn, so terminate the loop. Treat all other
|
||||
// errors as temporary and simply log them.
|
||||
if errors.Is(err, net.ErrClosed) {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
log.Printf("WriteTo error: %v", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@@ -814,7 +821,15 @@ func run(privkey []byte, domain dns.Name, upstream string, dnsConn net.PacketCon
|
||||
defer func() {
|
||||
_ = ln.Close()
|
||||
}()
|
||||
|
||||
// We will run acceptSessions, sendLoop, and recvLoop concurrently. The
|
||||
// first one to finish closes the done channel.
|
||||
doneChan := make(chan struct{})
|
||||
var doneOnce sync.Once
|
||||
done := func() { doneOnce.Do(func() { close(doneChan) }) }
|
||||
|
||||
go func() {
|
||||
defer done()
|
||||
err := acceptSessions(ln, privkey, mtu, upstream)
|
||||
if err != nil {
|
||||
log.Printf("acceptSessions: %v", err)
|
||||
@@ -828,13 +843,26 @@ func run(privkey []byte, domain dns.Name, upstream string, dnsConn net.PacketCon
|
||||
// for each response to collect downstream data before being evicted by
|
||||
// another response that needs to be sent.
|
||||
go func() {
|
||||
defer done()
|
||||
err := sendLoop(dnsConn, ttConn, ch, maxEncodedPayload)
|
||||
if err != nil {
|
||||
log.Printf("sendLoop: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
return recvLoop(domain, dnsConn, ttConn, ch)
|
||||
go func() {
|
||||
defer done()
|
||||
err := recvLoop(domain, dnsConn, ttConn, ch)
|
||||
if err != nil {
|
||||
log.Printf("recvLoop: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
// Wait for any of acceptSessions, sendLoop, or recvLoop to return. In
|
||||
// normal operation, we don't expect any of these to return.
|
||||
<-doneChan
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
Reference in New Issue
Block a user