2017-07-13 21:55:41 +08:00
package main
import (
"encoding/binary"
"io/ioutil"
"net"
)
type dnstun struct {
Proxy
addr string
raddr string
}
// DNSTunProxy returns a dns forwarder. client -> dns.udp -> glider -> forwarder -> remote dns addr
func DNSTunProxy ( addr , raddr string , upProxy Proxy ) ( Proxy , error ) {
s := & dnstun {
Proxy : upProxy ,
addr : addr ,
raddr : raddr ,
}
return s , nil
}
2017-07-16 12:16:50 +08:00
// ListenAndServe .
2017-07-13 21:55:41 +08:00
func ( s * dnstun ) ListenAndServe ( ) {
l , err := net . ListenPacket ( "udp" , s . addr )
if err != nil {
logf ( "failed to listen on %s: %v" , s . addr , err )
return
}
2017-07-16 12:16:50 +08:00
defer l . Close ( )
2017-07-13 21:55:41 +08:00
logf ( "listening UDP on %s" , s . addr )
for {
data := make ( [ ] byte , 512 )
n , clientAddr , err := l . ReadFrom ( data )
if err != nil {
logf ( "DNS local read error: %v" , err )
continue
}
data = data [ : n ]
go func ( ) {
rc , err := s . GetProxy ( ) . Dial ( "tcp" , s . raddr )
if err != nil {
logf ( "failed to connect to server %v: %v" , s . raddr , err )
return
}
defer rc . Close ( )
logf ( "proxy-dnstun %s[dns.udp] <-> %s[dns.tcp]" , clientAddr . String ( ) , s . raddr )
// 2 bytes length after tcp header, before dns message
length := make ( [ ] byte , 2 )
binary . BigEndian . PutUint16 ( length , uint16 ( len ( data ) ) )
rc . Write ( length )
rc . Write ( data )
2017-07-16 12:16:50 +08:00
resp , err := ioutil . ReadAll ( rc )
2017-07-13 21:55:41 +08:00
if err != nil {
logf ( "error in ioutil.ReadAll: %s\n" , err )
return
}
// length is not needed in udp dns response. (2 bytes)
// SEE RFC1035, section 4.2.2 TCP: The message is prefixed with a two byte length field which gives the message length, excluding the two byte length field.
2017-07-16 12:16:50 +08:00
if len ( resp ) > 2 {
msg := resp [ 2 : ]
2017-07-13 21:55:41 +08:00
_ , err = l . WriteTo ( msg , clientAddr )
if err != nil {
logf ( "error in local write: %s\n" , err )
}
}
} ( )
}
}