Compare commits

...
3 Commits
Author SHA1 Message Date
xjasonlyu fcf9d280b8 fix: ipv6 connect error 2020-11-09 21:19:44 +08:00
xjasonlyu f18362714d rm docker folder 2020-11-09 14:15:30 +08:00
xjasonlyu 95dc93cb41 improve: core udp 2020-11-09 10:33:55 +08:00
8 changed files with 45 additions and 67 deletions
+3 -3
View File
@@ -21,9 +21,7 @@ PLATFORM_LIST = \
openbsd-amd64 \
openbsd-arm64 \
.PHONY: all docker $(PLATFORM_LIST)
all: $(PLATFORM_LIST)
all: linux-amd64 darwin-amd64
docker:
$(GO_BUILD) -o $(DIR)/$(NAME)-$@
@@ -54,6 +52,8 @@ zip_releases=$(addsuffix .zip, $(PLATFORM_LIST))
$(zip_releases): %.zip : %
zip -m -j $(DIR)/$(NAME)-$(basename $@).zip $(DIR)/$(NAME)-$(basename $@)
all-arch: $(PLATFORM_LIST)
releases: $(zip_releases)
clean:
+1 -1
View File
@@ -71,7 +71,7 @@ $ docker build -t tun2socks .
or
```text
$ docker build -t tun2socks -f ./docker/Dockerfile.aarch64 .
$ docker build -t tun2socks -f .Dockerfile.aarch64 .
```
## QuickStart
+18 -59
View File
@@ -3,6 +3,7 @@ package core
import (
"fmt"
"net"
_ "unsafe"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/buffer"
@@ -103,7 +104,7 @@ func (p *udpPacket) WriteBack(b []byte, addr net.Addr) (int, error) {
data := v.ToVectorisedView()
// if addr is not provided, write back use original dst Addr as src Addr.
if addr == nil {
return sendUDP(p.r, data, p.id.LocalPort, p.id.RemotePort, udpNoChecksum)
return _sendUDP(p.r, data, p.id.LocalPort, p.id.RemotePort, udpNoChecksum)
}
udpAddr, ok := addr.(*net.UDPAddr)
@@ -113,75 +114,33 @@ func (p *udpPacket) WriteBack(b []byte, addr net.Addr) (int, error) {
r := p.r.Clone()
defer r.Release()
if ipv4 := udpAddr.IP.To4(); ipv4 != nil {
r.LocalAddress = tcpip.Address(ipv4)
} else {
r.LocalAddress = tcpip.Address(udpAddr.IP)
}
return sendUDP(&r, data, uint16(udpAddr.Port), p.id.RemotePort, udpNoChecksum)
return _sendUDP(&r, data, uint16(udpAddr.Port), p.id.RemotePort, udpNoChecksum)
}
// _sendUDP wraps sendUDP with some default parameters.
func _sendUDP(r *stack.Route, data buffer.VectorisedView, localPort, remotePort uint16, noChecksum bool) (int, error) {
if err := sendUDP(r, data, localPort, remotePort, 0 /* ttl */, true /* useDefaultTTL */, 0 /* tos */, nil /* owner */, noChecksum); err != nil {
return 0, fmt.Errorf("%s", err)
}
return data.Size(), nil
}
// sendUDP sends a UDP segment via the provided network endpoint and under the
// provided identity.
func sendUDP(r *stack.Route, data buffer.VectorisedView, localPort, remotePort uint16, noChecksum bool) (int, error) {
// Allocate a buffer for the UDP header.
pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
ReserveHeaderBytes: header.UDPMinimumSize + int(r.MaxHeaderLength()),
Data: data,
})
// Initialize the UDP header.
udpHdr := header.UDP(pkt.TransportHeader().Push(header.UDPMinimumSize))
pkt.TransportProtocolNumber = udp.ProtocolNumber
length := uint16(pkt.Size())
udpHdr.Encode(&header.UDPFields{
SrcPort: localPort,
DstPort: remotePort,
Length: length,
})
// Set the checksum field unless TX checksum offload is enabled.
// On IPv4, UDP checksum is optional, and a zero value indicates the
// transmitter skipped the checksum generation (RFC768).
// On IPv6, UDP checksum is not optional (RFC2460 Section 8.1).
if r.RequiresTXTransportChecksum() &&
(!noChecksum || r.NetProto == header.IPv6ProtocolNumber) {
xsum := r.PseudoHeaderChecksum(udp.ProtocolNumber, length)
for _, v := range data.Views() {
xsum = header.Checksum(v, xsum)
}
udpHdr.SetChecksum(^udpHdr.CalculateChecksum(xsum))
}
ttl := r.DefaultTTL()
if err := r.WritePacket(nil /* gso */, stack.NetworkHeaderParams{
Protocol: udp.ProtocolNumber,
TTL: ttl,
TOS: 0, /* default */
}, pkt); err != nil {
r.Stats().UDP.PacketSendErrors.Increment()
return 0, fmt.Errorf("%s", err)
}
// Track count of packets sent.
r.Stats().UDP.PacketsSent.Increment()
return data.Size(), nil
}
//
//go:linkname sendUDP gvisor.dev/gvisor/pkg/tcpip/transport/udp.sendUDP
func sendUDP(r *stack.Route, data buffer.VectorisedView, localPort, remotePort uint16, ttl uint8, useDefaultTTL bool, tos uint8, owner tcpip.PacketOwner, noChecksum bool) *tcpip.Error
// verifyChecksum verifies the checksum unless RX checksum offload is enabled.
// On IPv4, UDP checksum is optional, and a zero value means the transmitter
// omitted the checksum generation (RFC768).
// On IPv6, UDP checksum is not optional (RFC2460 Section 8.1).
func verifyChecksum(hdr header.UDP, pkt *stack.PacketBuffer) bool {
if !pkt.RXTransportChecksumValidated &&
(hdr.Checksum() != 0 || pkt.NetworkProtocolNumber == header.IPv6ProtocolNumber) {
netHdr := pkt.Network()
xsum := header.PseudoHeaderChecksum(udp.ProtocolNumber, netHdr.DestinationAddress(), netHdr.SourceAddress(), hdr.Length())
for _, v := range pkt.Data.Views() {
xsum = header.Checksum(v, xsum)
}
return hdr.CalculateChecksum(xsum) == 0xffff
}
return true
}
//
//go:linkname verifyChecksum gvisor.dev/gvisor/pkg/tcpip/transport/udp.verifyChecksum
func verifyChecksum(hdr header.UDP, pkt *stack.PacketBuffer) bool
+7 -1
View File
@@ -4,9 +4,15 @@ import (
"net"
"github.com/xjasonlyu/clash/component/dialer"
"github.com/xjasonlyu/clash/component/resolver"
)
func init() { /* use bound dialer to resolve DNS */
func init() {
// enable ipv6
resolver.DisableIPv6 = false
// use bound dialer to resolve DNS
net.DefaultResolver.PreferGo = true
net.DefaultResolver.Dial = dialer.DialContext
}
+4 -1
View File
@@ -31,7 +31,10 @@ func Start(dnsURL string, rawHosts []string) error {
return errors.New("unsupported scheme")
}
var serverAddr = u.Host
serverAddr := u.Host
if serverAddr == "" {
return nil
}
fakeIPRange := u.Query().Get("fake-ip-range")
if fakeIPRange == "" {
+12 -2
View File
@@ -92,7 +92,7 @@ func (ss *Socks5) DialUDP(_ *adapter.Metadata) (_ net.PacketConn, err error) {
// zeros. RFC1928
var targetAddr socks5.Addr = []byte{socks5.AtypIPv4, 0, 0, 0, 0, 0, 0}
bindAddr, err := socks5.ClientHandshake(c, targetAddr, socks5.CmdUDPAssociate, user)
addr, err := socks5.ClientHandshake(c, targetAddr, socks5.CmdUDPAssociate, user)
if err != nil {
return nil, fmt.Errorf("client hanshake: %w", err)
}
@@ -110,7 +110,17 @@ func (ss *Socks5) DialUDP(_ *adapter.Metadata) (_ net.PacketConn, err error) {
pc.Close()
}()
return &socksPacketConn{PacketConn: pc, rAddr: bindAddr.UDPAddr(), tcpConn: c}, nil
bindAddr := addr.UDPAddr()
if bindAddr.IP.IsUnspecified() {
udpAddr, err := resolveUDPAddr("udp", ss.Addr())
if err != nil {
return nil, err
}
bindAddr.IP = udpAddr.IP
}
return &socksPacketConn{PacketConn: pc, rAddr: bindAddr, tcpConn: c}, nil
}
type socksPacketConn struct {