Skip to content
This repository has been archived by the owner on Jan 28, 2025. It is now read-only.

Commit

Permalink
Merge branch 'XTLS:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
MHSanaei authored Jul 29, 2024
2 parents 27231ed + 33daa0c commit 1aec3fc
Show file tree
Hide file tree
Showing 23 changed files with 729 additions and 250 deletions.
28 changes: 17 additions & 11 deletions .github/docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,27 @@
FROM --platform=$BUILDPLATFORM golang:alpine AS build
WORKDIR /src
COPY . .
ARG TARGETOS TARGETARCH
ARG TARGETOS
ARG TARGETARCH
RUN GOOS=$TARGETOS GOARCH=$TARGETARCH CGO_ENABLED=0 go build -o xray -trimpath -ldflags "-s -w -buildid=" ./main
ADD https://github.com/v2fly/geoip/releases/latest/download/geoip.dat /v2fly/geoip.dat
ADD https://github.com/v2fly/domain-list-community/releases/latest/download/dlc.dat /v2fly/geosite.dat
ADD https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat /loyalsoldier/geoip.dat
ADD https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat /loyalsoldier/geosite.dat

FROM --platform=${TARGETPLATFORM} alpine:latest
WORKDIR /root
# chainguard/static contains only tzdata and ca-certificates, can be built with multiarch static binaries.
FROM --platform=linux/amd64 chainguard/static:latest
WORKDIR /var/log/xray
COPY .github/docker/files/config.json /etc/xray/config.json
COPY --from=build /src/xray /usr/bin/xray
RUN set -ex \
&& apk add --no-cache tzdata ca-certificates \
&& mkdir -p /var/log/xray /usr/share/xray \
&& chmod +x /usr/bin/xray \
&& wget -O /usr/share/xray/geosite.dat https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat \
&& wget -O /usr/share/xray/geoip.dat https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat
COPY --from=build --chmod=755 /src/xray /usr/bin/xray

USER root
WORKDIR /root
VOLUME /etc/xray
ENV TZ=Asia/Shanghai
ARG TZ=Asia/Shanghai
ENV TZ=$TZ
ENTRYPOINT [ "/usr/bin/xray" ]
CMD [ "-config", "/etc/xray/config.json" ]

ARG flavor=v2fly
COPY --from=build /$flavor /usr/share/xray
42 changes: 35 additions & 7 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,20 @@ jobs:
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository_owner }}/xray-core
flavor: latest=true
flavor: latest=auto
tags: |
type=sha
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
- name: Docker metadata Loyalsoldier flavor
id: loyalsoldier
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository_owner }}/xray-core
flavor: |
latest=auto
suffix=-ls,onlatest=true
tags: |
type=sha
type=ref,event=branch
Expand All @@ -31,18 +44,33 @@ jobs:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- # Add support for more platforms with QEMU (optional)
# https://github.com/docker/setup-qemu-action
name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
platforms: linux/amd64,linux/arm64
platforms: |
linux/amd64
linux/arm64
linux/loong64
linux/riscv64
provenance: false
file: .github/docker/Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
- name: Build and push Loyalsoldier flavor
uses: docker/build-push-action@v6
with:
context: .
platforms: |
linux/amd64
linux/arm64
linux/loong64
linux/riscv64
provenance: false
file: .github/docker/Dockerfile
build-args: flavor=loyalsoldier
push: true
tags: |
${{ steps.loyalsoldier.outputs.tags }}
15 changes: 11 additions & 4 deletions common/protocol/tls/cert/cert.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,10 +149,6 @@ func Generate(parent *Certificate, opts ...Option) (*Certificate, error) {
BasicConstraintsValid: true,
}

for _, opt := range opts {
opt(template)
}

parentCert := template
if parent != nil {
pCert, err := x509.ParseCertificate(parent.Certificate)
Expand All @@ -162,6 +158,17 @@ func Generate(parent *Certificate, opts ...Option) (*Certificate, error) {
parentCert = pCert
}

if parentCert.NotAfter.Before(template.NotAfter) {
template.NotAfter = parentCert.NotAfter
}
if parentCert.NotBefore.After(template.NotBefore) {
template.NotBefore = parentCert.NotBefore
}

for _, opt := range opts {
opt(template)
}

derBytes, err := x509.CreateCertificate(rand.Reader, template, parentCert, publicKey(selfKey), parentKey)
if err != nil {
return nil, errors.New("failed to create certificate").Base(err)
Expand Down
2 changes: 1 addition & 1 deletion core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
var (
Version_x byte = 1
Version_y byte = 8
Version_z byte = 21
Version_z byte = 22
)

var (
Expand Down
31 changes: 31 additions & 0 deletions infra/conf/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package conf

import (
"encoding/json"
"strconv"
"strings"

"github.com/xtls/xray-core/common/errors"
Expand Down Expand Up @@ -242,3 +243,33 @@ func (v *User) Build() *protocol.User {
Level: uint32(v.LevelByte),
}
}

// Int32Range deserializes from "1-2" or 1, so can deserialize from both int and number.
// Negative integers can be passed as sentinel values, but do not parse as ranges.
type Int32Range struct {
From int32
To int32
}

func (v *Int32Range) UnmarshalJSON(data []byte) error {
var stringrange string
var rawint int32
if err := json.Unmarshal(data, &stringrange); err == nil {
pair := strings.SplitN(stringrange, "-", 2)
if len(pair) == 2 {
from, err := strconv.Atoi(pair[0])
to, err2 := strconv.Atoi(pair[1])
if err == nil && err2 == nil {
v.From = int32(from)
v.To = int32(to)
return nil
}
}
} else if err := json.Unmarshal(data, &rawint); err == nil {
v.From = rawint
v.To = rawint
return nil
}

return errors.New("Invalid integer range, expected either string of form \"1-2\" or plain integer.")
}
29 changes: 22 additions & 7 deletions infra/conf/transport_internet.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,8 +229,10 @@ type SplitHTTPConfig struct {
Host string `json:"host"`
Path string `json:"path"`
Headers map[string]string `json:"headers"`
MaxConcurrentUploads int32 `json:"maxConcurrentUploads"`
MaxUploadSize int32 `json:"maxUploadSize"`
MaxConcurrentUploads Int32Range `json:"maxConcurrentUploads"`
MaxUploadSize Int32Range `json:"maxUploadSize"`
MinUploadIntervalMs Int32Range `json:"minUploadIntervalMs"`
NoSSEHeader bool `json:"noSSEHeader"`
}

// Build implements Buildable.
Expand All @@ -244,11 +246,22 @@ func (c *SplitHTTPConfig) Build() (proto.Message, error) {
c.Host = c.Headers["Host"]
}
config := &splithttp.Config{
Path: c.Path,
Host: c.Host,
Header: c.Headers,
MaxConcurrentUploads: c.MaxConcurrentUploads,
MaxUploadSize: c.MaxUploadSize,
Path: c.Path,
Host: c.Host,
Header: c.Headers,
MaxConcurrentUploads: &splithttp.RandRangeConfig{
From: c.MaxConcurrentUploads.From,
To: c.MaxConcurrentUploads.To,
},
MaxUploadSize: &splithttp.RandRangeConfig{
From: c.MaxUploadSize.From,
To: c.MaxUploadSize.To,
},
MinUploadIntervalMs: &splithttp.RandRangeConfig{
From: c.MinUploadIntervalMs.From,
To: c.MinUploadIntervalMs.To,
},
NoSSEHeader: c.NoSSEHeader,
}
return config, nil
}
Expand Down Expand Up @@ -372,6 +385,7 @@ type TLSCertConfig struct {
Usage string `json:"usage"`
OcspStapling uint64 `json:"ocspStapling"`
OneTimeLoading bool `json:"oneTimeLoading"`
BuildChain bool `json:"buildChain"`
}

// Build implements Buildable.
Expand Down Expand Up @@ -410,6 +424,7 @@ func (c *TLSCertConfig) Build() (*tls.Certificate, error) {
certificate.OneTimeLoading = c.OneTimeLoading
}
certificate.OcspStapling = c.OcspStapling
certificate.BuildChain = c.BuildChain

return certificate, nil
}
Expand Down
25 changes: 23 additions & 2 deletions proxy/freedom/freedom.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"github.com/xtls/xray-core/transport"
"github.com/xtls/xray-core/transport/internet"
"github.com/xtls/xray-core/transport/internet/stat"
"github.com/xtls/xray-core/transport/internet/tls"
)

var useSplice bool
Expand Down Expand Up @@ -225,9 +226,16 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
writeConn = inbound.Conn
inTimer = inbound.Timer
}
return proxy.CopyRawConnIfExist(ctx, conn, writeConn, link.Writer, timer, inTimer)
if !isTLSConn(conn) { // it would be tls conn in special use case of MITM, we need to let link handle traffic
return proxy.CopyRawConnIfExist(ctx, conn, writeConn, link.Writer, timer, inTimer)
}
}
var reader buf.Reader
if destination.Network == net.Network_TCP {
reader = buf.NewReader(conn)
} else {
reader = NewPacketReader(conn, UDPOverride)
}
reader := NewPacketReader(conn, UDPOverride)
if err := buf.Copy(reader, output, buf.UpdateActivity(timer)); err != nil {
return errors.New("failed to process response").Base(err)
}
Expand All @@ -245,6 +253,19 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
return nil
}

func isTLSConn(conn stat.Connection) bool {
if conn != nil {
statConn, ok := conn.(*stat.CounterConnection)
if ok {
conn = statConn.Connection
}
if _, ok := conn.(*tls.Conn); ok {
return true
}
}
return false
}

func NewPacketReader(conn net.Conn, UDPOverride net.Destination) buf.Reader {
iConn := conn
statConn, ok := iConn.(*stat.CounterConnection)
Expand Down
25 changes: 12 additions & 13 deletions proxy/wireguard/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func (h *Handler) processWireGuard(ctx context.Context, dialer internet.Dialer)
}

// bind := conn.NewStdNetBind() // TODO: conn.Bind wrapper for dialer
bind := &netBindClient{
h.bind = &netBindClient{
netBind: netBind{
dns: h.dns,
dnsOption: dns.IPOption{
Expand All @@ -115,15 +115,14 @@ func (h *Handler) processWireGuard(ctx context.Context, dialer internet.Dialer)
}
defer func() {
if err != nil {
_ = bind.Close()
_ = h.bind.Close()
}
}()

h.net, err = h.makeVirtualTun(bind)
h.net, err = h.makeVirtualTun()
if err != nil {
return errors.New("failed to create virtual tun interface").Base(err)
}
h.bind = bind
return nil
}

Expand Down Expand Up @@ -238,34 +237,34 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
}

// creates a tun interface on netstack given a configuration
func (h *Handler) makeVirtualTun(bind *netBindClient) (Tunnel, error) {
func (h *Handler) makeVirtualTun() (Tunnel, error) {
t, err := h.conf.createTun()(h.endpoints, int(h.conf.Mtu), nil)
if err != nil {
return nil, err
}

bind.dnsOption.IPv4Enable = h.hasIPv4
bind.dnsOption.IPv6Enable = h.hasIPv6
h.bind.dnsOption.IPv4Enable = h.hasIPv4
h.bind.dnsOption.IPv6Enable = h.hasIPv6

if err = t.BuildDevice(h.createIPCRequest(bind, h.conf), bind); err != nil {
if err = t.BuildDevice(h.createIPCRequest(), h.bind); err != nil {
_ = t.Close()
return nil, err
}
return t, nil
}

// serialize the config into an IPC request
func (h *Handler) createIPCRequest(bind *netBindClient, conf *DeviceConfig) string {
func (h *Handler) createIPCRequest() string {
var request strings.Builder

request.WriteString(fmt.Sprintf("private_key=%s\n", conf.SecretKey))
request.WriteString(fmt.Sprintf("private_key=%s\n", h.conf.SecretKey))

if !conf.IsClient {
if !h.conf.IsClient {
// placeholder, we'll handle actual port listening on Xray
request.WriteString("listen_port=1337\n")
}

for _, peer := range conf.Peers {
for _, peer := range h.conf.Peers {
if peer.PublicKey != "" {
request.WriteString(fmt.Sprintf("public_key=%s\n", peer.PublicKey))
}
Expand All @@ -280,7 +279,7 @@ func (h *Handler) createIPCRequest(bind *netBindClient, conf *DeviceConfig) stri
}
addr := net.ParseAddress(address)
if addr.Family().IsDomain() {
dialerIp := bind.dialer.DestIpAddress()
dialerIp := h.bind.dialer.DestIpAddress()
if dialerIp != nil {
addr = net.ParseAddress(dialerIp.String())
errors.LogInfo(h.bind.ctx, "createIPCRequest use dialer dest ip: ", addr)
Expand Down
Loading

0 comments on commit 1aec3fc

Please sign in to comment.