diff --git a/.github/workflows/release-win7.yml b/.github/workflows/release-win7.yml index 239de1b5..6595dc07 100644 --- a/.github/workflows/release-win7.yml +++ b/.github/workflows/release-win7.yml @@ -51,7 +51,7 @@ jobs: GOSDK=$(go env GOROOT) rm -r $GOSDK/* cd $GOSDK - curl -O -L https://github.com/XTLS/go-win7/releases/latest/download/go-for-win7-linux-amd64.zip + curl -O -L -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" https://github.com/XTLS/go-win7/releases/latest/download/go-for-win7-linux-amd64.zip unzip ./go-for-win7-linux-amd64.zip -d $GOSDK rm ./go-for-win7-linux-amd64.zip diff --git a/.github/workflows/scheduled-assets-update.yml b/.github/workflows/scheduled-assets-update.yml index fb3ca455..c5149d92 100644 --- a/.github/workflows/scheduled-assets-update.yml +++ b/.github/workflows/scheduled-assets-update.yml @@ -45,12 +45,12 @@ jobs: INFO=($(echo $i | awk 'BEGIN{FS=" ";OFS=" "} {print $1,$2,$3,$4}')) FILE_NAME="${INFO[3]}.dat" echo -e "Verifying HASH key..." - HASH="$(curl -sL "https://raw.githubusercontent.com/${INFO[0]}/${INFO[1]}/release/${INFO[2]}.dat.sha256sum" | awk -F ' ' '{print $1}')" + HASH="$(curl -sL -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" "https://raw.githubusercontent.com/${INFO[0]}/${INFO[1]}/release/${INFO[2]}.dat.sha256sum" | awk -F ' ' '{print $1}')" if [ -s "./resources/${FILE_NAME}" ] && [ "$(sha256sum "./resources/${FILE_NAME}" | awk -F ' ' '{print $1}')" == "${HASH}" ]; then continue else echo -e "Downloading https://raw.githubusercontent.com/${INFO[0]}/${INFO[1]}/release/${INFO[2]}.dat..." - curl -L "https://raw.githubusercontent.com/${INFO[0]}/${INFO[1]}/release/${INFO[2]}.dat" -o ./resources/${FILE_NAME} + curl -L -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" "https://raw.githubusercontent.com/${INFO[0]}/${INFO[1]}/release/${INFO[2]}.dat" -o ./resources/${FILE_NAME} echo -e "Verifying HASH key..." [ "$(sha256sum "./resources/${FILE_NAME}" | awk -F ' ' '{print $1}')" == "${HASH}" ] || { echo -e "The HASH key of ${FILE_NAME} does not match cloud one."; exit 1; } echo "unhit=true" >> $GITHUB_OUTPUT diff --git a/app/dns/hosts.go b/app/dns/hosts.go index e1ceb9c7..f4e06dbb 100644 --- a/app/dns/hosts.go +++ b/app/dns/hosts.go @@ -2,7 +2,6 @@ package dns import ( "context" - "github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/strmatcher" @@ -41,8 +40,6 @@ func NewStaticHosts(hosts []*Config_HostMapping) (*StaticHosts, error) { } ips = append(ips, addr) } - default: - return nil, errors.New("neither IP address nor proxied domain specified for domain: ", mapping.Domain).AtWarning() } sh.ips[id] = ips @@ -62,9 +59,14 @@ func filterIP(ips []net.Address, option dns.IPOption) []net.Address { } func (h *StaticHosts) lookupInternal(domain string) []net.Address { - var ips []net.Address + ips := make([]net.Address, 0) + found := false for _, id := range h.matchers.Match(domain) { ips = append(ips, h.ips[id]...) + found = true + } + if !found { + return nil } return ips } @@ -72,7 +74,7 @@ func (h *StaticHosts) lookupInternal(domain string) []net.Address { func (h *StaticHosts) lookup(domain string, option dns.IPOption, maxDepth int) []net.Address { switch addrs := h.lookupInternal(domain); { case len(addrs) == 0: // Not recorded in static hosts, return nil - return nil + return addrs case len(addrs) == 1 && addrs[0].Family().IsDomain(): // Try to unwrap domain errors.LogDebug(context.Background(), "found replaced domain: ", domain, " -> ", addrs[0].Domain(), ". Try to unwrap it") if maxDepth > 0 { diff --git a/app/proxyman/outbound/handler.go b/app/proxyman/outbound/handler.go index ab44a1d5..9a91480f 100644 --- a/app/proxyman/outbound/handler.go +++ b/app/proxyman/outbound/handler.go @@ -241,7 +241,9 @@ func (h *Handler) DestIpAddress() net.IP { // Dial implements internet.Dialer. func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connection, error) { if h.senderSettings != nil { + if h.senderSettings.ProxySettings.HasTag() { + tag := h.senderSettings.ProxySettings.Tag handler := h.outboundManager.GetHandler(tag) if handler != nil { @@ -270,22 +272,40 @@ func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connecti } if h.senderSettings.Via != nil { + outbounds := session.OutboundsFromContext(ctx) ob := outbounds[len(outbounds)-1] - if h.senderSettings.ViaCidr == "" { - if h.senderSettings.Via.AsAddress().Family().IsDomain() && h.senderSettings.Via.AsAddress().Domain() == "origin" { - if inbound := session.InboundFromContext(ctx); inbound != nil { - origin, _, err := net.SplitHostPort(inbound.Conn.LocalAddr().String()) - if err == nil { - ob.Gateway = net.ParseAddress(origin) - } - } - } else { - ob.Gateway = h.senderSettings.Via.AsAddress() - } - } else { //Get a random address. - ob.Gateway = ParseRandomIPv6(h.senderSettings.Via.AsAddress(), h.senderSettings.ViaCidr) + addr := h.senderSettings.Via.AsAddress() + var domain string + if addr.Family().IsDomain() { + domain = addr.Domain() } + switch { + case h.senderSettings.ViaCidr != "": + ob.Gateway = ParseRandomIP(addr, h.senderSettings.ViaCidr) + + case domain == "origin": + + if inbound := session.InboundFromContext(ctx); inbound != nil { + origin, _, err := net.SplitHostPort(inbound.Conn.LocalAddr().String()) + if err == nil { + ob.Gateway = net.ParseAddress(origin) + } + + } + case domain == "srcip": + if inbound := session.InboundFromContext(ctx); inbound != nil { + srcip, _, err := net.SplitHostPort(inbound.Conn.RemoteAddr().String()) + if err == nil { + ob.Gateway = net.ParseAddress(srcip) + } + } + //case addr.Family().IsDomain(): + default: + ob.Gateway = addr + + } + } } @@ -329,20 +349,21 @@ func (h *Handler) Close() error { return nil } -func ParseRandomIPv6(address net.Address, prefix string) net.Address { - _, network, _ := gonet.ParseCIDR(address.IP().String() + "/" + prefix) +func ParseRandomIP(addr net.Address, prefix string) net.Address { - maskSize, totalBits := network.Mask.Size() - subnetSize := big.NewInt(1).Lsh(big.NewInt(1), uint(totalBits-maskSize)) + _, ipnet, _ := gonet.ParseCIDR(addr.IP().String() + "/" + prefix) - // random - randomBigInt, _ := rand.Int(rand.Reader, subnetSize) + ones, bits := ipnet.Mask.Size() + subnetSize := new(big.Int).Lsh(big.NewInt(1), uint(bits-ones)) - startIPBigInt := big.NewInt(0).SetBytes(network.IP.To16()) - randomIPBigInt := big.NewInt(0).Add(startIPBigInt, randomBigInt) + rnd, _ := rand.Int(rand.Reader, subnetSize) - randomIPBytes := randomIPBigInt.Bytes() - randomIPBytes = append(make([]byte, 16-len(randomIPBytes)), randomIPBytes...) + startInt := new(big.Int).SetBytes(ipnet.IP) + rndInt := new(big.Int).Add(startInt, rnd) - return net.ParseAddress(gonet.IP(randomIPBytes).String()) + rndBytes := rndInt.Bytes() + padded := make([]byte, len(ipnet.IP)) + copy(padded[len(padded)-len(rndBytes):], rndBytes) + + return net.ParseAddress(gonet.IP(padded).String()) } diff --git a/core/core.go b/core/core.go index 4e512118..d7555674 100644 --- a/core/core.go +++ b/core/core.go @@ -18,8 +18,8 @@ import ( var ( Version_x byte = 25 - Version_y byte = 3 - Version_z byte = 31 + Version_y byte = 4 + Version_z byte = 30 ) var ( diff --git a/go.mod b/go.mod index c2c6eb31..d162fec8 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/gorilla/websocket v1.5.3 github.com/miekg/dns v1.1.65 github.com/pelletier/go-toml v1.9.5 - github.com/pires/go-proxyproto v0.8.0 + github.com/pires/go-proxyproto v0.8.1 github.com/quic-go/quic-go v0.51.0 github.com/refraction-networking/utls v1.7.1 github.com/sagernet/sing v0.5.1 @@ -22,10 +22,10 @@ require ( github.com/vishvananda/netlink v1.3.0 github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d go4.org/netipx v0.0.0-20231129151722-fdeea329fbba - golang.org/x/crypto v0.37.0 - golang.org/x/net v0.39.0 - golang.org/x/sync v0.13.0 - golang.org/x/sys v0.32.0 + golang.org/x/crypto v0.38.0 + golang.org/x/net v0.40.0 + golang.org/x/sync v0.14.0 + golang.org/x/sys v0.33.0 golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 google.golang.org/grpc v1.72.0 google.golang.org/protobuf v1.36.6 @@ -50,7 +50,7 @@ require ( github.com/vishvananda/netns v0.0.4 // indirect go.uber.org/mock v0.5.0 // indirect golang.org/x/mod v0.23.0 // indirect - golang.org/x/text v0.24.0 // indirect + golang.org/x/text v0.25.0 // indirect golang.org/x/time v0.7.0 // indirect golang.org/x/tools v0.30.0 // indirect golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect diff --git a/go.sum b/go.sum index ccc00031..b06e1f7d 100644 --- a/go.sum +++ b/go.sum @@ -48,8 +48,8 @@ github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3v github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc= github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= -github.com/pires/go-proxyproto v0.8.0 h1:5unRmEAPbHXHuLjDg01CxJWf91cw3lKHc/0xzKpXEe0= -github.com/pires/go-proxyproto v0.8.0/go.mod h1:iknsfgnH8EkjrMeMyvfKByp9TiBZCKZM0jx2xmKqnVY= +github.com/pires/go-proxyproto v0.8.1 h1:9KEixbdJfhrbtjpz/ZwCdWDD2Xem0NZ38qMYaASJgp0= +github.com/pires/go-proxyproto v0.8.1/go.mod h1:ZKAAyp3cgy5Y5Mo4n9AlScrkCZwUy0g3Jf+slqQVcuU= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI= @@ -97,20 +97,20 @@ go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBs go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= -golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= +golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= +golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= -golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= +golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= +golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= -golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= +golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -119,14 +119,14 @@ golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= -golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= -golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= +golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= +golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=