├── common
├── peer
│ ├── peer.go
│ └── latency.go
├── protocol
│ ├── tls
│ │ └── cert
│ │ │ ├── .gitignore
│ │ │ ├── errors.generated.go
│ │ │ └── privateKey.go
│ ├── udp
│ │ ├── udp.go
│ │ └── packet.go
│ ├── protocol.go
│ ├── dns
│ │ └── errors.generated.go
│ ├── errors.generated.go
│ ├── account.go
│ ├── payload.go
│ ├── context.go
│ ├── id_test.go
│ ├── time.go
│ ├── headers.proto
│ ├── time_test.go
│ ├── server_spec.proto
│ ├── user.proto
│ ├── bittorrent
│ │ └── bittorrent.go
│ └── user.go
├── mux
│ ├── mux.go
│ ├── errors.generated.go
│ ├── frame_test.go
│ └── session_test.go
├── antireplay
│ ├── antireplay.go
│ └── bloomring.go
├── buf
│ ├── buf.go
│ ├── errors.generated.go
│ ├── readv_reader_wasm.go
│ ├── readv_unix.go
│ ├── readv_windows.go
│ └── readv_posix.go
├── crypto
│ ├── crypto.go
│ ├── errors.generated.go
│ └── chacha20.go
├── platform
│ ├── ctlcmd
│ │ ├── attr_other.go
│ │ ├── attr_windows.go
│ │ └── errors.generated.go
│ └── windows.go
├── net
│ ├── net.go
│ ├── errors.generated.go
│ ├── port_test.go
│ ├── network.go
│ ├── destination.proto
│ ├── network.proto
│ ├── address.proto
│ └── port.proto
├── drain
│ ├── drain.go
│ └── errors.generated.go
├── task
│ ├── common.go
│ ├── periodic_test.go
│ └── task.go
├── errors.generated.go
├── retry
│ └── errors.generated.go
├── signal
│ ├── notifier_test.go
│ ├── pubsub
│ │ └── pubsub_test.go
│ ├── semaphore
│ │ └── semaphore.go
│ ├── notifier.go
│ └── done
│ │ └── done.go
├── cmdarg
│ └── cmdarg.go
├── bitmask
│ ├── byte.go
│ └── byte_test.go
├── log
│ ├── log.proto
│ ├── log_test.go
│ └── logger_test.go
├── serial
│ ├── typed_message_test.go
│ ├── typed_message.proto
│ ├── string.go
│ └── serial.go
├── errors
│ ├── multi_error.go
│ └── errorgen
│ │ └── main.go
├── strmatcher
│ ├── full_matcher.go
│ ├── full_matcher_test.go
│ └── matchers.go
├── dice
│ └── dice_test.go
├── type_test.go
└── common_test.go
├── proxy
├── freedom
│ ├── config.go
│ ├── errors.generated.go
│ └── config.proto
├── trojan
│ ├── trojan.go
│ ├── errors.generated.go
│ └── config.proto
├── vmess
│ ├── outbound
│ │ ├── config.go
│ │ ├── errors.generated.go
│ │ └── config.proto
│ ├── vmessCtxInterface.go
│ ├── errors.generated.go
│ ├── encoding
│ │ ├── errors.generated.go
│ │ ├── encoding.go
│ │ └── auth_test.go
│ ├── inbound
│ │ ├── errors.generated.go
│ │ ├── config.go
│ │ └── config.proto
│ ├── vmess.go
│ ├── aead
│ │ ├── kdf_test.go
│ │ ├── consts.go
│ │ └── kdf.go
│ └── account.proto
├── http
│ ├── http.go
│ ├── errors.generated.go
│ ├── config.go
│ └── config.proto
├── loopback
│ ├── config.go
│ ├── errors.generated.go
│ └── config.proto
├── socks
│ ├── socks.go
│ ├── errors.generated.go
│ └── config.go
├── dns
│ ├── errors.generated.go
│ └── config.proto
├── blackhole
│ ├── errors.generated.go
│ ├── config.proto
│ └── config_test.go
├── dokodemo
│ ├── errors.generated.go
│ ├── config.go
│ └── config.proto
└── shadowsocks
│ ├── errors.generated.go
│ ├── shadowsocks.go
│ ├── config.proto
│ └── config_test.go
├── release
├── debian
│ ├── source
│ │ └── format
│ ├── v2ray-docs.docs
│ ├── v2ray-geoip.install
│ ├── v2ray.install
│ ├── v2ray-domain-list-community.install
│ ├── v2ray@.service
│ ├── v2ray.service
│ └── rules
├── config
│ ├── sysusers.d
│ │ └── v2ray.conf
│ ├── tmpfiles.d
│ │ └── v2ray.conf
│ └── systemd
│ │ └── system
│ │ ├── v2ray.service
│ │ └── v2ray@.service
├── extra
│ └── browserforwarder
│ │ └── index.html
├── install-release.sh
└── requestsign.sh
├── infra
├── conf
│ ├── conf.go
│ ├── serial
│ │ ├── serial.go
│ │ └── errors.generated.go
│ ├── init.go
│ ├── router_strategy.go
│ ├── buildable.go
│ ├── errors.generated.go
│ ├── rule
│ │ └── errors.generated.go
│ ├── command
│ │ └── errors.generated.go
│ ├── geodata
│ │ ├── errors.generated.go
│ │ ├── standard
│ │ │ └── errors.generated.go
│ │ ├── memconservative
│ │ │ └── errors.generated.go
│ │ └── geodataproto.go
│ ├── cfgcommon
│ │ ├── errors.generated.go
│ │ └── duration
│ │ │ ├── duration.go
│ │ │ └── duration_test.go
│ ├── gun.go
│ ├── loopback.go
│ ├── browser_forwarder.go
│ ├── observatory.go
│ ├── dns_proxy.go
│ ├── policy_test.go
│ ├── blackhole_test.go
│ ├── dns_proxy_test.go
│ ├── lint.go
│ ├── http_test.go
│ ├── dokodemo.go
│ ├── services.go
│ ├── dokodemo_test.go
│ ├── reverse_test.go
│ ├── freedom_test.go
│ ├── shadowsocks_test.go
│ └── general_test.go
└── control
│ ├── control.go
│ ├── errors.generated.go
│ ├── uuid.go
│ └── command.go
├── app
├── app.go
├── proxyman
│ ├── command
│ │ ├── doc.go
│ │ └── errors.generated.go
│ ├── inbound
│ │ └── errors.generated.go
│ └── outbound
│ │ └── errors.generated.go
├── observatory
│ ├── observatory.go
│ ├── errors.generated.go
│ ├── explainErrors.go
│ └── command
│ │ └── command.proto
├── dns
│ ├── fakedns
│ │ ├── fakedns.go
│ │ ├── errors.generated.go
│ │ └── fakedns.proto
│ ├── errors.generated.go
│ └── nameserver_local_test.go
├── dispatcher
│ ├── dispatcher.go
│ ├── errors.generated.go
│ ├── config.proto
│ ├── stats.go
│ └── stats_test.go
├── policy
│ ├── policy.go
│ └── errors.generated.go
├── log
│ ├── errors.generated.go
│ ├── command
│ │ ├── errors.generated.go
│ │ ├── config.proto
│ │ └── command_test.go
│ └── config.proto
├── stats
│ ├── errors.generated.go
│ ├── command
│ │ └── errors.generated.go
│ ├── config.proto
│ ├── counter.go
│ └── counter_test.go
├── reverse
│ ├── errors.generated.go
│ ├── config.go
│ ├── portal_test.go
│ └── config.proto
├── router
│ ├── errors.generated.go
│ └── command
│ │ └── errors.generated.go
├── commander
│ ├── errors.generated.go
│ ├── service.go
│ └── config.proto
└── browserforwarder
│ ├── errors.generated.go
│ └── config.proto
├── format.go
├── transport
├── internet
│ ├── tcp
│ │ ├── tcp.go
│ │ ├── errors.generated.go
│ │ ├── sockopt_other.go
│ │ ├── config.go
│ │ ├── config.proto
│ │ ├── sockopt_freebsd.go
│ │ └── sockopt_linux_test.go
│ ├── http
│ │ ├── http.go
│ │ ├── errors.generated.go
│ │ ├── config.proto
│ │ └── config.go
│ ├── internet.go
│ ├── kcp
│ │ ├── xor_amd64.go
│ │ ├── errors.generated.go
│ │ ├── kcp.go
│ │ ├── cryptreal.go
│ │ ├── xor.go
│ │ ├── io_test.go
│ │ ├── xor_amd64.s
│ │ ├── connection_test.go
│ │ └── crypt_test.go
│ ├── domainsocket
│ │ ├── errgen.go
│ │ ├── errors.generated.go
│ │ ├── config.proto
│ │ └── config.go
│ ├── grpc
│ │ ├── encoding
│ │ │ ├── encoding.go
│ │ │ ├── errors.generated.go
│ │ │ └── stream.proto
│ │ ├── grpc.go
│ │ ├── config.proto
│ │ ├── errors.generated.go
│ │ └── config.go
│ ├── tagged
│ │ ├── taggedimpl
│ │ │ ├── taggedimpl.go
│ │ │ └── errors.generated.go
│ │ └── tagged.go
│ ├── udp
│ │ ├── udp.go
│ │ ├── errors.generated.go
│ │ ├── config.go
│ │ ├── config.proto
│ │ ├── hub_other.go
│ │ ├── dialer.go
│ │ ├── hub_linux.go
│ │ └── hub_freebsd.go
│ ├── filelocker.go
│ ├── filelocker_windows.go
│ ├── tls
│ │ ├── errors.generated.go
│ │ ├── config_windows.go
│ │ └── pin.go
│ ├── errors.generated.go
│ ├── quic
│ │ ├── errors.generated.go
│ │ ├── pool.go
│ │ ├── config.proto
│ │ └── quic.go
│ ├── headers
│ │ ├── http
│ │ │ ├── errors.generated.go
│ │ │ ├── linkedreadRequest.go
│ │ │ └── resp.go
│ │ ├── tls
│ │ │ ├── config.proto
│ │ │ └── dtls_test.go
│ │ ├── wechat
│ │ │ ├── config.proto
│ │ │ ├── wechat_test.go
│ │ │ └── wechat.go
│ │ ├── utp
│ │ │ ├── config.proto
│ │ │ ├── utp_test.go
│ │ │ └── utp.go
│ │ ├── wireguard
│ │ │ ├── config.proto
│ │ │ └── wireguard.go
│ │ ├── noop
│ │ │ ├── config.proto
│ │ │ └── noop.go
│ │ └── srtp
│ │ │ ├── config.proto
│ │ │ ├── srtp_test.go
│ │ │ └── srtp.go
│ ├── websocket
│ │ ├── errors.generated.go
│ │ ├── ws.go
│ │ ├── config.proto
│ │ └── config.go
│ ├── sockopt.go
│ ├── system_dns_android_test.go
│ ├── system_dialer_other.go
│ ├── sockopt_other.go
│ ├── system_listener_test.go
│ ├── connection.go
│ ├── system_dns_android.go
│ ├── dialer_test.go
│ ├── filelocker_other.go
│ ├── header.go
│ ├── sockopt_test.go
│ └── memory_settings.go
├── link.go
├── config.go
├── config.proto
└── pipe
│ ├── writer.go
│ └── reader.go
├── features
├── extension
│ ├── contextreceiver.go
│ ├── browser.go
│ └── observatory.go
├── errors.generated.go
├── stats
│ └── errors.generated.go
├── routing
│ ├── dns
│ │ └── errors.generated.go
│ └── dispatcher.go
├── dns
│ ├── localdns
│ │ └── errors.generated.go
│ └── fakedns.go
├── policy
│ └── default.go
└── feature.go
├── main
├── distro
│ └── debug
│ │ └── debug.go
├── main_test.go
├── errors.generated.go
├── json
│ └── errors.generated.go
├── jsonem
│ └── errors.generated.go
└── confloader
│ ├── errors.generated.go
│ ├── external
│ └── errors.generated.go
│ └── confloader.go
├── proto.go
├── errors.generated.go
├── context_test.go
├── .gitignore
├── testing
├── servers
│ ├── tcp
│ │ └── port.go
│ ├── udp
│ │ └── port.go
│ └── http
│ │ └── http.go
└── scenarios
│ ├── common_regular.go
│ └── common_coverage.go
├── .github
├── dependabot.yml
├── linters
│ └── .golangci.yml
└── workflows
│ └── linter.yml
├── annotations.go
└── mocks.go
/common/peer/peer.go:
--------------------------------------------------------------------------------
1 | package peer
2 |
--------------------------------------------------------------------------------
/common/protocol/tls/cert/.gitignore:
--------------------------------------------------------------------------------
1 | *.pem
--------------------------------------------------------------------------------
/common/protocol/udp/udp.go:
--------------------------------------------------------------------------------
1 | package udp
2 |
--------------------------------------------------------------------------------
/proxy/freedom/config.go:
--------------------------------------------------------------------------------
1 | package freedom
2 |
--------------------------------------------------------------------------------
/proxy/trojan/trojan.go:
--------------------------------------------------------------------------------
1 | package trojan
2 |
--------------------------------------------------------------------------------
/release/debian/source/format:
--------------------------------------------------------------------------------
1 | 3.0 (quilt)
2 |
--------------------------------------------------------------------------------
/release/debian/v2ray-docs.docs:
--------------------------------------------------------------------------------
1 | README.md
2 |
--------------------------------------------------------------------------------
/proxy/vmess/outbound/config.go:
--------------------------------------------------------------------------------
1 | package outbound
2 |
--------------------------------------------------------------------------------
/release/config/sysusers.d/v2ray.conf:
--------------------------------------------------------------------------------
1 | u v2ray - "V2Ray"
2 |
--------------------------------------------------------------------------------
/release/config/tmpfiles.d/v2ray.conf:
--------------------------------------------------------------------------------
1 | d /etc/v2ray 0755 v2ray network -
2 |
--------------------------------------------------------------------------------
/release/debian/v2ray-geoip.install:
--------------------------------------------------------------------------------
1 | release/config/geoip.dat usr/share/v2ray
2 |
--------------------------------------------------------------------------------
/release/debian/v2ray.install:
--------------------------------------------------------------------------------
1 | usr/bin
2 | release/config/config.json etc/v2ray
3 |
--------------------------------------------------------------------------------
/release/debian/v2ray-domain-list-community.install:
--------------------------------------------------------------------------------
1 | release/config/geosite.dat usr/share/v2ray
2 |
--------------------------------------------------------------------------------
/proxy/vmess/vmessCtxInterface.go:
--------------------------------------------------------------------------------
1 | package vmess
2 |
3 | // example
4 | const AlterID = "VMessCtxInterface_AlterID"
5 |
--------------------------------------------------------------------------------
/common/mux/mux.go:
--------------------------------------------------------------------------------
1 | package mux
2 |
3 | //go:generate go run github.com/Shadowsocks-NET/v2ray-go/v4/common/errors/errorgen
4 |
--------------------------------------------------------------------------------
/infra/conf/conf.go:
--------------------------------------------------------------------------------
1 | package conf
2 |
3 | //go:generate go run github.com/Shadowsocks-NET/v2ray-go/v4/common/errors/errorgen
4 |
--------------------------------------------------------------------------------
/proxy/http/http.go:
--------------------------------------------------------------------------------
1 | package http
2 |
3 | //go:generate go run github.com/Shadowsocks-NET/v2ray-go/v4/common/errors/errorgen
4 |
--------------------------------------------------------------------------------
/app/app.go:
--------------------------------------------------------------------------------
1 | // Package app contains feature implementations of V2Ray. The features may be enabled during runtime.
2 | package app
3 |
--------------------------------------------------------------------------------
/format.go:
--------------------------------------------------------------------------------
1 | package core
2 |
3 | //go:generate go install -v github.com/daixiang0/gci@latest
4 | //go:generate go run ./infra/vformat/
5 |
--------------------------------------------------------------------------------
/infra/conf/serial/serial.go:
--------------------------------------------------------------------------------
1 | package serial
2 |
3 | //go:generate go run github.com/Shadowsocks-NET/v2ray-go/v4/common/errors/errorgen
4 |
--------------------------------------------------------------------------------
/infra/control/control.go:
--------------------------------------------------------------------------------
1 | package control
2 |
3 | //go:generate go run github.com/Shadowsocks-NET/v2ray-go/v4/common/errors/errorgen
4 |
--------------------------------------------------------------------------------
/proxy/loopback/config.go:
--------------------------------------------------------------------------------
1 | package loopback
2 |
3 | //go:generate go run github.com/Shadowsocks-NET/v2ray-go/v4/common/errors/errorgen
4 |
--------------------------------------------------------------------------------
/transport/internet/tcp/tcp.go:
--------------------------------------------------------------------------------
1 | package tcp
2 |
3 | //go:generate go run github.com/Shadowsocks-NET/v2ray-go/v4/common/errors/errorgen
4 |
--------------------------------------------------------------------------------
/app/proxyman/command/doc.go:
--------------------------------------------------------------------------------
1 | package command
2 |
3 | //go:generate go run github.com/Shadowsocks-NET/v2ray-go/v4/common/errors/errorgen
4 |
--------------------------------------------------------------------------------
/common/protocol/protocol.go:
--------------------------------------------------------------------------------
1 | package protocol
2 |
3 | //go:generate go run github.com/Shadowsocks-NET/v2ray-go/v4/common/errors/errorgen
4 |
--------------------------------------------------------------------------------
/transport/internet/http/http.go:
--------------------------------------------------------------------------------
1 | package http
2 |
3 | //go:generate go run github.com/Shadowsocks-NET/v2ray-go/v4/common/errors/errorgen
4 |
--------------------------------------------------------------------------------
/transport/internet/internet.go:
--------------------------------------------------------------------------------
1 | package internet
2 |
3 | //go:generate go run github.com/Shadowsocks-NET/v2ray-go/v4/common/errors/errorgen
4 |
--------------------------------------------------------------------------------
/app/observatory/observatory.go:
--------------------------------------------------------------------------------
1 | package observatory
2 |
3 | //go:generate go run github.com/Shadowsocks-NET/v2ray-go/v4/common/errors/errorgen
4 |
--------------------------------------------------------------------------------
/infra/conf/init.go:
--------------------------------------------------------------------------------
1 | package conf
2 |
3 | func init() {
4 | RegisterConfigureFilePostProcessingStage("FakeDNS", &FakeDNSPostProcessingStage{})
5 | }
6 |
--------------------------------------------------------------------------------
/transport/internet/kcp/xor_amd64.go:
--------------------------------------------------------------------------------
1 | package kcp
2 |
3 | //go:noescape
4 | func xorfwd(x []byte)
5 |
6 | //go:noescape
7 | func xorbkd(x []byte)
8 |
--------------------------------------------------------------------------------
/infra/conf/router_strategy.go:
--------------------------------------------------------------------------------
1 | package conf
2 |
3 | const (
4 | strategyRandom string = "random"
5 | strategyLeastPing string = "leastping"
6 | )
7 |
--------------------------------------------------------------------------------
/transport/internet/domainsocket/errgen.go:
--------------------------------------------------------------------------------
1 | package domainsocket
2 |
3 | //go:generate go run github.com/Shadowsocks-NET/v2ray-go/v4/common/errors/errorgen
4 |
--------------------------------------------------------------------------------
/transport/internet/grpc/encoding/encoding.go:
--------------------------------------------------------------------------------
1 | package encoding
2 |
3 | //go:generate go run github.com/Shadowsocks-NET/v2ray-go/v4/common/errors/errorgen
4 |
--------------------------------------------------------------------------------
/common/antireplay/antireplay.go:
--------------------------------------------------------------------------------
1 | package antireplay
2 |
3 | type GeneralizedReplayFilter interface {
4 | Interval() int64
5 | Check(sum []byte) bool
6 | }
7 |
--------------------------------------------------------------------------------
/transport/internet/tagged/taggedimpl/taggedimpl.go:
--------------------------------------------------------------------------------
1 | package taggedimpl
2 |
3 | //go:generate go run github.com/Shadowsocks-NET/v2ray-go/v4/common/errors/errorgen
4 |
--------------------------------------------------------------------------------
/features/extension/contextreceiver.go:
--------------------------------------------------------------------------------
1 | package extension
2 |
3 | import "context"
4 |
5 | type ContextReceiver interface {
6 | InjectContext(ctx context.Context)
7 | }
8 |
--------------------------------------------------------------------------------
/infra/conf/buildable.go:
--------------------------------------------------------------------------------
1 | package conf
2 |
3 | import "github.com/golang/protobuf/proto"
4 |
5 | type Buildable interface {
6 | Build() (proto.Message, error)
7 | }
8 |
--------------------------------------------------------------------------------
/transport/internet/udp/udp.go:
--------------------------------------------------------------------------------
1 | package udp
2 |
3 | //go:generate go run github.com/Shadowsocks-NET/v2ray-go/v4/common/errors/errorgen
4 |
5 | const protocolName = "udp"
6 |
--------------------------------------------------------------------------------
/app/dns/fakedns/fakedns.go:
--------------------------------------------------------------------------------
1 | //go:build !confonly
2 | // +build !confonly
3 |
4 | package fakedns
5 |
6 | //go:generate go run github.com/Shadowsocks-NET/v2ray-go/v4/common/errors/errorgen
7 |
--------------------------------------------------------------------------------
/main/distro/debug/debug.go:
--------------------------------------------------------------------------------
1 | package debug
2 |
3 | import (
4 | "net/http"
5 | )
6 |
7 | func init() {
8 | go func() {
9 | http.ListenAndServe(":6060", nil)
10 | }()
11 | }
12 |
--------------------------------------------------------------------------------
/app/dispatcher/dispatcher.go:
--------------------------------------------------------------------------------
1 | //go:build !confonly
2 | // +build !confonly
3 |
4 | package dispatcher
5 |
6 | //go:generate go run github.com/Shadowsocks-NET/v2ray-go/v4/common/errors/errorgen
7 |
--------------------------------------------------------------------------------
/common/buf/buf.go:
--------------------------------------------------------------------------------
1 | // Package buf provides a light-weight memory allocation mechanism.
2 | package buf
3 |
4 | //go:generate go run github.com/Shadowsocks-NET/v2ray-go/v4/common/errors/errorgen
5 |
--------------------------------------------------------------------------------
/transport/internet/grpc/grpc.go:
--------------------------------------------------------------------------------
1 | //go:build !confonly
2 | // +build !confonly
3 |
4 | package grpc
5 |
6 | //go:generate go run github.com/Shadowsocks-NET/v2ray-go/v4/common/errors/errorgen
7 |
--------------------------------------------------------------------------------
/app/policy/policy.go:
--------------------------------------------------------------------------------
1 | // Package policy is an implementation of policy.Manager feature.
2 | package policy
3 |
4 | //go:generate go run github.com/Shadowsocks-NET/v2ray-go/v4/common/errors/errorgen
5 |
--------------------------------------------------------------------------------
/common/crypto/crypto.go:
--------------------------------------------------------------------------------
1 | // Package crypto provides common crypto libraries for V2Ray.
2 | package crypto
3 |
4 | //go:generate go run github.com/Shadowsocks-NET/v2ray-go/v4/common/errors/errorgen
5 |
--------------------------------------------------------------------------------
/proxy/socks/socks.go:
--------------------------------------------------------------------------------
1 | // Package socks provides implements of Socks protocol 4, 4a and 5.
2 | package socks
3 |
4 | //go:generate go run github.com/Shadowsocks-NET/v2ray-go/v4/common/errors/errorgen
5 |
--------------------------------------------------------------------------------
/transport/internet/filelocker.go:
--------------------------------------------------------------------------------
1 | package internet
2 |
3 | import (
4 | "os"
5 | )
6 |
7 | // FileLocker is UDS access lock
8 | type FileLocker struct {
9 | path string
10 | file *os.File
11 | }
12 |
--------------------------------------------------------------------------------
/main/main_test.go:
--------------------------------------------------------------------------------
1 | //go:build coveragemain
2 | // +build coveragemain
3 |
4 | package main
5 |
6 | import (
7 | "testing"
8 | )
9 |
10 | func TestRunMainForCoverage(t *testing.T) {
11 | main()
12 | }
13 |
--------------------------------------------------------------------------------
/common/platform/ctlcmd/attr_other.go:
--------------------------------------------------------------------------------
1 | //go:build !windows
2 | // +build !windows
3 |
4 | package ctlcmd
5 |
6 | import "syscall"
7 |
8 | func getSysProcAttr() *syscall.SysProcAttr {
9 | return nil
10 | }
11 |
--------------------------------------------------------------------------------
/common/net/net.go:
--------------------------------------------------------------------------------
1 | // Package net is a drop-in replacement to Golang's net package, with some more functionalities.
2 | package net
3 |
4 | //go:generate go run github.com/Shadowsocks-NET/v2ray-go/v4/common/errors/errorgen
5 |
--------------------------------------------------------------------------------
/proto.go:
--------------------------------------------------------------------------------
1 | package core
2 |
3 | //go:generate go install -v google.golang.org/protobuf/cmd/protoc-gen-go@latest
4 | //go:generate go install -v google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
5 | //go:generate go run ./infra/vprotogen/
6 |
--------------------------------------------------------------------------------
/transport/internet/filelocker_windows.go:
--------------------------------------------------------------------------------
1 | package internet
2 |
3 | // Acquire lock
4 | func (fl *FileLocker) Acquire() error {
5 | return nil
6 | }
7 |
8 | // Release lock
9 | func (fl *FileLocker) Release() {
10 | return
11 | }
12 |
--------------------------------------------------------------------------------
/common/drain/drain.go:
--------------------------------------------------------------------------------
1 | package drain
2 |
3 | import "io"
4 |
5 | //go:generate go run github.com/Shadowsocks-NET/v2ray-go/v4/common/errors/errorgen
6 |
7 | type Drainer interface {
8 | AcknowledgeReceive(size int)
9 | Drain(reader io.Reader) error
10 | }
11 |
--------------------------------------------------------------------------------
/common/platform/ctlcmd/attr_windows.go:
--------------------------------------------------------------------------------
1 | //go:build windows
2 | // +build windows
3 |
4 | package ctlcmd
5 |
6 | import "syscall"
7 |
8 | func getSysProcAttr() *syscall.SysProcAttr {
9 | return &syscall.SysProcAttr{
10 | HideWindow: true,
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/common/task/common.go:
--------------------------------------------------------------------------------
1 | package task
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common"
4 |
5 | // Close returns a func() that closes v.
6 | func Close(v interface{}) func() error {
7 | return func() error {
8 | return common.Close(v)
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/release/extra/browserforwarder/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Bridge
6 |
7 |
8 | See debug console for detail
9 |
10 |
11 |
--------------------------------------------------------------------------------
/transport/internet/grpc/config.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 | package v2ray.core.transport.internet.grpc.encoding;
3 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/transport/internet/grpc";
4 |
5 | message Config {
6 | string host = 1;
7 | string service_name = 2;
8 | }
--------------------------------------------------------------------------------
/transport/link.go:
--------------------------------------------------------------------------------
1 | package transport
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/buf"
4 |
5 | // Link is a utility for connecting between an inbound and an outbound proxy handler.
6 | type Link struct {
7 | Reader buf.Reader
8 | Writer buf.Writer
9 | }
10 |
--------------------------------------------------------------------------------
/errors.generated.go:
--------------------------------------------------------------------------------
1 | package core
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/app/dns/errors.generated.go:
--------------------------------------------------------------------------------
1 | package dns
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/app/log/errors.generated.go:
--------------------------------------------------------------------------------
1 | package log
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/main/errors.generated.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/transport/internet/tagged/tagged.go:
--------------------------------------------------------------------------------
1 | package tagged
2 |
3 | import (
4 | "context"
5 |
6 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/net"
7 | )
8 |
9 | type DialFunc func(ctx context.Context, dest net.Destination, tag string) (net.Conn, error)
10 |
11 | var Dialer DialFunc
12 |
--------------------------------------------------------------------------------
/app/stats/errors.generated.go:
--------------------------------------------------------------------------------
1 | package stats
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/common/buf/errors.generated.go:
--------------------------------------------------------------------------------
1 | package buf
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/common/errors.generated.go:
--------------------------------------------------------------------------------
1 | package common
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/common/mux/errors.generated.go:
--------------------------------------------------------------------------------
1 | package mux
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/common/net/errors.generated.go:
--------------------------------------------------------------------------------
1 | package net
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/infra/conf/errors.generated.go:
--------------------------------------------------------------------------------
1 | package conf
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/main/json/errors.generated.go:
--------------------------------------------------------------------------------
1 | package json
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/proxy/dns/errors.generated.go:
--------------------------------------------------------------------------------
1 | package dns
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/proxy/http/errors.generated.go:
--------------------------------------------------------------------------------
1 | package http
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/app/policy/errors.generated.go:
--------------------------------------------------------------------------------
1 | package policy
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/app/reverse/errors.generated.go:
--------------------------------------------------------------------------------
1 | package reverse
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/app/router/errors.generated.go:
--------------------------------------------------------------------------------
1 | package router
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/common/buf/readv_reader_wasm.go:
--------------------------------------------------------------------------------
1 | //go:build wasm
2 | // +build wasm
3 |
4 | package buf
5 |
6 | import (
7 | "io"
8 | "syscall"
9 | )
10 |
11 | const useReadv = false
12 |
13 | func NewReadVReader(reader io.Reader, rawConn syscall.RawConn) Reader {
14 | panic("not implemented")
15 | }
16 |
--------------------------------------------------------------------------------
/common/crypto/errors.generated.go:
--------------------------------------------------------------------------------
1 | package crypto
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/common/drain/errors.generated.go:
--------------------------------------------------------------------------------
1 | package drain
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/common/retry/errors.generated.go:
--------------------------------------------------------------------------------
1 | package retry
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/features/errors.generated.go:
--------------------------------------------------------------------------------
1 | package features
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/features/stats/errors.generated.go:
--------------------------------------------------------------------------------
1 | package stats
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/infra/conf/rule/errors.generated.go:
--------------------------------------------------------------------------------
1 | package rule
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/infra/control/errors.generated.go:
--------------------------------------------------------------------------------
1 | package control
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/main/jsonem/errors.generated.go:
--------------------------------------------------------------------------------
1 | package jsonem
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/proxy/freedom/errors.generated.go:
--------------------------------------------------------------------------------
1 | package freedom
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/proxy/socks/errors.generated.go:
--------------------------------------------------------------------------------
1 | package socks
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/proxy/trojan/errors.generated.go:
--------------------------------------------------------------------------------
1 | package trojan
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/proxy/vmess/errors.generated.go:
--------------------------------------------------------------------------------
1 | package vmess
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/app/commander/errors.generated.go:
--------------------------------------------------------------------------------
1 | package commander
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/app/dispatcher/errors.generated.go:
--------------------------------------------------------------------------------
1 | package dispatcher
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/app/dns/fakedns/errors.generated.go:
--------------------------------------------------------------------------------
1 | package fakedns
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/app/log/command/errors.generated.go:
--------------------------------------------------------------------------------
1 | package command
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/app/router/command/errors.generated.go:
--------------------------------------------------------------------------------
1 | package command
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/app/stats/command/errors.generated.go:
--------------------------------------------------------------------------------
1 | package command
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/common/protocol/dns/errors.generated.go:
--------------------------------------------------------------------------------
1 | package dns
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/common/protocol/errors.generated.go:
--------------------------------------------------------------------------------
1 | package protocol
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/features/routing/dns/errors.generated.go:
--------------------------------------------------------------------------------
1 | package dns
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/infra/conf/command/errors.generated.go:
--------------------------------------------------------------------------------
1 | package command
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/infra/conf/geodata/errors.generated.go:
--------------------------------------------------------------------------------
1 | package geodata
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/infra/conf/serial/errors.generated.go:
--------------------------------------------------------------------------------
1 | package serial
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/main/confloader/errors.generated.go:
--------------------------------------------------------------------------------
1 | package confloader
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/proxy/blackhole/errors.generated.go:
--------------------------------------------------------------------------------
1 | package blackhole
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/proxy/dokodemo/errors.generated.go:
--------------------------------------------------------------------------------
1 | package dokodemo
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/proxy/loopback/errors.generated.go:
--------------------------------------------------------------------------------
1 | package loopback
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/transport/internet/kcp/errors.generated.go:
--------------------------------------------------------------------------------
1 | package kcp
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/transport/internet/tcp/errors.generated.go:
--------------------------------------------------------------------------------
1 | package tcp
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/transport/internet/tls/errors.generated.go:
--------------------------------------------------------------------------------
1 | package tls
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/transport/internet/udp/errors.generated.go:
--------------------------------------------------------------------------------
1 | package udp
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/app/observatory/errors.generated.go:
--------------------------------------------------------------------------------
1 | package observatory
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/app/proxyman/command/errors.generated.go:
--------------------------------------------------------------------------------
1 | package command
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/app/proxyman/inbound/errors.generated.go:
--------------------------------------------------------------------------------
1 | package inbound
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/app/proxyman/outbound/errors.generated.go:
--------------------------------------------------------------------------------
1 | package outbound
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/common/platform/ctlcmd/errors.generated.go:
--------------------------------------------------------------------------------
1 | package ctlcmd
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/common/protocol/tls/cert/errors.generated.go:
--------------------------------------------------------------------------------
1 | package cert
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/features/dns/localdns/errors.generated.go:
--------------------------------------------------------------------------------
1 | package localdns
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/infra/conf/cfgcommon/errors.generated.go:
--------------------------------------------------------------------------------
1 | package cfgcommon
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/proxy/shadowsocks/errors.generated.go:
--------------------------------------------------------------------------------
1 | package shadowsocks
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/proxy/vmess/encoding/errors.generated.go:
--------------------------------------------------------------------------------
1 | package encoding
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/proxy/vmess/inbound/errors.generated.go:
--------------------------------------------------------------------------------
1 | package inbound
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/proxy/vmess/outbound/errors.generated.go:
--------------------------------------------------------------------------------
1 | package outbound
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/transport/internet/errors.generated.go:
--------------------------------------------------------------------------------
1 | package internet
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/transport/internet/grpc/errors.generated.go:
--------------------------------------------------------------------------------
1 | package grpc
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/transport/internet/http/errors.generated.go:
--------------------------------------------------------------------------------
1 | package http
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/transport/internet/quic/errors.generated.go:
--------------------------------------------------------------------------------
1 | package quic
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/common/protocol/account.go:
--------------------------------------------------------------------------------
1 | package protocol
2 |
3 | // Account is a user identity used for authentication.
4 | type Account interface {
5 | Equals(Account) bool
6 | }
7 |
8 | // AsAccount is an object can be converted into account.
9 | type AsAccount interface {
10 | AsAccount() (Account, error)
11 | }
12 |
--------------------------------------------------------------------------------
/infra/conf/geodata/standard/errors.generated.go:
--------------------------------------------------------------------------------
1 | package standard
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/main/confloader/external/errors.generated.go:
--------------------------------------------------------------------------------
1 | package external
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/transport/internet/headers/http/errors.generated.go:
--------------------------------------------------------------------------------
1 | package http
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/app/browserforwarder/errors.generated.go:
--------------------------------------------------------------------------------
1 | package browserforwarder
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/transport/internet/grpc/encoding/errors.generated.go:
--------------------------------------------------------------------------------
1 | package encoding
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/transport/internet/websocket/errors.generated.go:
--------------------------------------------------------------------------------
1 | package websocket
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/transport/internet/domainsocket/errors.generated.go:
--------------------------------------------------------------------------------
1 | package domainsocket
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/transport/internet/kcp/kcp.go:
--------------------------------------------------------------------------------
1 | // Package kcp - A Fast and Reliable ARQ Protocol
2 | //
3 | // Acknowledgement:
4 | // skywind3000@github for inventing the KCP protocol
5 | // xtaci@github for translating to Golang
6 | package kcp
7 |
8 | //go:generate go run github.com/Shadowsocks-NET/v2ray-go/v4/common/errors/errorgen
9 |
--------------------------------------------------------------------------------
/features/extension/browser.go:
--------------------------------------------------------------------------------
1 | package extension
2 |
3 | import (
4 | "io"
5 | "net/http"
6 | )
7 |
8 | type BrowserForwarder interface {
9 | DialWebsocket(url string, header http.Header) (io.ReadWriteCloser, error)
10 | }
11 |
12 | func BrowserForwarderType() interface{} {
13 | return (*BrowserForwarder)(nil)
14 | }
15 |
--------------------------------------------------------------------------------
/infra/conf/geodata/memconservative/errors.generated.go:
--------------------------------------------------------------------------------
1 | package memconservative
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/transport/internet/tagged/taggedimpl/errors.generated.go:
--------------------------------------------------------------------------------
1 | package taggedimpl
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errPathObjHolder struct{}
6 |
7 | func newError(values ...interface{}) *errors.Error {
8 | return errors.New(values...).WithPathObj(errPathObjHolder{})
9 | }
10 |
--------------------------------------------------------------------------------
/transport/internet/websocket/ws.go:
--------------------------------------------------------------------------------
1 | /*Package websocket implements Websocket transport
2 |
3 | Websocket transport implements an HTTP(S) compliable, surveillance proof transport method with plausible deniability.
4 | */
5 | package websocket
6 |
7 | //go:generate go run github.com/Shadowsocks-NET/v2ray-go/v4/common/errors/errorgen
8 |
--------------------------------------------------------------------------------
/proxy/vmess/inbound/config.go:
--------------------------------------------------------------------------------
1 | //go:build !confonly
2 | // +build !confonly
3 |
4 | package inbound
5 |
6 | // GetDefaultValue returns default settings of DefaultConfig.
7 | func (c *Config) GetDefaultValue() *DefaultConfig {
8 | if c.GetDefault() == nil {
9 | return &DefaultConfig{}
10 | }
11 | return c.Default
12 | }
13 |
--------------------------------------------------------------------------------
/transport/config.go:
--------------------------------------------------------------------------------
1 | package transport
2 |
3 | import (
4 | "github.com/Shadowsocks-NET/v2ray-go/v4/transport/internet"
5 | )
6 |
7 | // Apply applies this Config.
8 | func (c *Config) Apply() error {
9 | if c == nil {
10 | return nil
11 | }
12 | return internet.ApplyGlobalTransportSettings(c.TransportSettings)
13 | }
14 |
--------------------------------------------------------------------------------
/transport/internet/headers/http/linkedreadRequest.go:
--------------------------------------------------------------------------------
1 | package http
2 |
3 | import (
4 | "bufio"
5 | "net/http"
6 |
7 | // required to use go:linkname
8 | _ "unsafe"
9 | )
10 |
11 | //go:linkname readRequest net/http.readRequest
12 | func readRequest(b *bufio.Reader, deleteHostHeader bool) (req *http.Request, err error)
13 |
--------------------------------------------------------------------------------
/transport/internet/tls/config_windows.go:
--------------------------------------------------------------------------------
1 | //go:build windows && !confonly
2 | // +build windows,!confonly
3 |
4 | package tls
5 |
6 | import "crypto/x509"
7 |
8 | func (c *Config) getCertPool() (*x509.CertPool, error) {
9 | if c.DisableSystemRoot {
10 | return c.loadSelfCertPool()
11 | }
12 |
13 | return nil, nil
14 | }
15 |
--------------------------------------------------------------------------------
/transport/internet/udp/config.go:
--------------------------------------------------------------------------------
1 | package udp
2 |
3 | import (
4 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
5 | "github.com/Shadowsocks-NET/v2ray-go/v4/transport/internet"
6 | )
7 |
8 | func init() {
9 | common.Must(internet.RegisterProtocolConfigCreator(protocolName, func() interface{} {
10 | return new(Config)
11 | }))
12 | }
13 |
--------------------------------------------------------------------------------
/common/protocol/payload.go:
--------------------------------------------------------------------------------
1 | package protocol
2 |
3 | type TransferType byte
4 |
5 | const (
6 | TransferTypeStream TransferType = 0
7 | TransferTypePacket TransferType = 1
8 | )
9 |
10 | type AddressType byte
11 |
12 | const (
13 | AddressTypeIPv4 AddressType = 1
14 | AddressTypeDomain AddressType = 2
15 | AddressTypeIPv6 AddressType = 3
16 | )
17 |
--------------------------------------------------------------------------------
/common/signal/notifier_test.go:
--------------------------------------------------------------------------------
1 | package signal_test
2 |
3 | import (
4 | "testing"
5 |
6 | . "github.com/Shadowsocks-NET/v2ray-go/v4/common/signal"
7 | )
8 |
9 | func TestNotifierSignal(t *testing.T) {
10 | n := NewNotifier()
11 |
12 | w := n.Wait()
13 | n.Signal()
14 |
15 | select {
16 | case <-w:
17 | default:
18 | t.Fail()
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/proxy/shadowsocks/shadowsocks.go:
--------------------------------------------------------------------------------
1 | // Package shadowsocks provides compatible functionality to Shadowsocks.
2 | //
3 | // Shadowsocks client and server are implemented as outbound and inbound respectively in V2Ray's term.
4 | //
5 | // R.I.P Shadowsocks
6 | package shadowsocks
7 |
8 | //go:generate go run github.com/Shadowsocks-NET/v2ray-go/v4/common/errors/errorgen
9 |
--------------------------------------------------------------------------------
/transport/internet/grpc/encoding/stream.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 | package v2ray.core.transport.internet.grpc.encoding;
3 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/transport/internet/grpc/encoding";
4 |
5 | message Hunk {
6 | bytes data = 1;
7 | }
8 |
9 | service GunService {
10 | rpc Tun (stream Hunk) returns (stream Hunk);
11 | }
12 |
--------------------------------------------------------------------------------
/app/reverse/config.go:
--------------------------------------------------------------------------------
1 | //go:build !confonly
2 | // +build !confonly
3 |
4 | package reverse
5 |
6 | import (
7 | "crypto/rand"
8 | "io"
9 |
10 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/dice"
11 | )
12 |
13 | func (c *Control) FillInRandom() {
14 | randomLength := dice.Roll(64)
15 | c.Random = make([]byte, randomLength)
16 | io.ReadFull(rand.Reader, c.Random)
17 | }
18 |
--------------------------------------------------------------------------------
/common/protocol/udp/packet.go:
--------------------------------------------------------------------------------
1 | package udp
2 |
3 | import (
4 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/buf"
5 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/net"
6 | )
7 |
8 | // Packet is a UDP packet together with its source and destination address.
9 | type Packet struct {
10 | Payload *buf.Buffer
11 | Source net.Destination
12 | Target net.Destination
13 | }
14 |
--------------------------------------------------------------------------------
/infra/conf/gun.go:
--------------------------------------------------------------------------------
1 | package conf
2 |
3 | import (
4 | "github.com/golang/protobuf/proto"
5 |
6 | "github.com/Shadowsocks-NET/v2ray-go/v4/transport/internet/grpc"
7 | )
8 |
9 | type GunConfig struct {
10 | ServiceName string `json:"serviceName"`
11 | }
12 |
13 | func (g GunConfig) Build() (proto.Message, error) {
14 | return &grpc.Config{ServiceName: g.ServiceName}, nil
15 | }
16 |
--------------------------------------------------------------------------------
/transport/internet/grpc/config.go:
--------------------------------------------------------------------------------
1 | package grpc
2 |
3 | import (
4 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
5 | "github.com/Shadowsocks-NET/v2ray-go/v4/transport/internet"
6 | )
7 |
8 | const protocolName = "gun"
9 |
10 | func init() {
11 | common.Must(internet.RegisterProtocolConfigCreator(protocolName, func() interface{} {
12 | return new(Config)
13 | }))
14 | }
15 |
--------------------------------------------------------------------------------
/common/cmdarg/cmdarg.go:
--------------------------------------------------------------------------------
1 | package cmdarg
2 |
3 | import "strings"
4 |
5 | // Arg is used by flag to accept multiple argument.
6 | type Arg []string
7 |
8 | func (c *Arg) String() string {
9 | return strings.Join([]string(*c), " ")
10 | }
11 |
12 | // Set is the method flag package calls
13 | func (c *Arg) Set(value string) error {
14 | *c = append(*c, value)
15 | return nil
16 | }
17 |
--------------------------------------------------------------------------------
/context_test.go:
--------------------------------------------------------------------------------
1 | package core_test
2 |
3 | import (
4 | "context"
5 | "testing"
6 | _ "unsafe"
7 |
8 | . "github.com/Shadowsocks-NET/v2ray-go/v4"
9 | )
10 |
11 | func TestFromContextPanic(t *testing.T) {
12 | defer func() {
13 | r := recover()
14 | if r == nil {
15 | t.Error("expect panic, but nil")
16 | }
17 | }()
18 |
19 | MustFromContext(context.Background())
20 | }
21 |
--------------------------------------------------------------------------------
/infra/conf/loopback.go:
--------------------------------------------------------------------------------
1 | package conf
2 |
3 | import (
4 | "github.com/golang/protobuf/proto"
5 |
6 | "github.com/Shadowsocks-NET/v2ray-go/v4/proxy/loopback"
7 | )
8 |
9 | type LoopbackConfig struct {
10 | InboundTag string `json:"inboundTag"`
11 | }
12 |
13 | func (l LoopbackConfig) Build() (proto.Message, error) {
14 | return &loopback.Config{InboundTag: l.InboundTag}, nil
15 | }
16 |
--------------------------------------------------------------------------------
/proxy/loopback/config.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.proxy.loopback;
4 | option csharp_namespace = "V2Ray.Core.Proxy.Loopback";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/proxy/loopback";
6 | option java_package = "com.v2ray.core.proxy.loopback";
7 | option java_multiple_files = true;
8 |
9 | message Config {
10 | string inbound_tag = 1;
11 | }
12 |
--------------------------------------------------------------------------------
/transport/internet/sockopt.go:
--------------------------------------------------------------------------------
1 | package internet
2 |
3 | func isTCPSocket(network string) bool {
4 | switch network {
5 | case "tcp", "tcp4", "tcp6":
6 | return true
7 | default:
8 | return false
9 | }
10 | }
11 |
12 | func isUDPSocket(network string) bool {
13 | switch network {
14 | case "udp", "udp4", "udp6":
15 | return true
16 | default:
17 | return false
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/proxy/dokodemo/config.go:
--------------------------------------------------------------------------------
1 | package dokodemo
2 |
3 | import (
4 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/net"
5 | )
6 |
7 | // GetPredefinedAddress returns the defined address from proto config. Null if address is not valid.
8 | func (v *Config) GetPredefinedAddress() net.Address {
9 | addr := v.Address.AsAddress()
10 | if addr == nil {
11 | return nil
12 | }
13 | return addr
14 | }
15 |
--------------------------------------------------------------------------------
/transport/internet/udp/config.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.transport.internet.udp;
4 | option csharp_namespace = "V2Ray.Core.Transport.Internet.Udp";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/transport/internet/udp";
6 | option java_package = "com.v2ray.core.transport.internet.udp";
7 | option java_multiple_files = true;
8 |
9 | message Config {}
10 |
--------------------------------------------------------------------------------
/common/net/port_test.go:
--------------------------------------------------------------------------------
1 | package net_test
2 |
3 | import (
4 | "testing"
5 |
6 | . "github.com/Shadowsocks-NET/v2ray-go/v4/common/net"
7 | )
8 |
9 | func TestPortRangeContains(t *testing.T) {
10 | portRange := &PortRange{
11 | From: 53,
12 | To: 53,
13 | }
14 |
15 | if !portRange.Contains(Port(53)) {
16 | t.Error("expected port range containing 53, but actually not")
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/transport/internet/system_dns_android_test.go:
--------------------------------------------------------------------------------
1 | //go:build android
2 | // +build android
3 |
4 | package internet
5 |
6 | import (
7 | "context"
8 | "testing"
9 | )
10 |
11 | func TestDNSResolver(t *testing.T) {
12 | resolver := NewDNSResolver()
13 | if ips, err := resolver.LookupIP(context.Background(), "ip", "www.google.com"); err != nil {
14 | t.Errorf("failed to lookupIP, %v, %v", ips, err)
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/features/extension/observatory.go:
--------------------------------------------------------------------------------
1 | package extension
2 |
3 | import (
4 | "context"
5 |
6 | "github.com/golang/protobuf/proto"
7 |
8 | "github.com/Shadowsocks-NET/v2ray-go/v4/features"
9 | )
10 |
11 | type Observatory interface {
12 | features.Feature
13 |
14 | GetObservation(ctx context.Context) (proto.Message, error)
15 | }
16 |
17 | func ObservatoryType() interface{} {
18 | return (*Observatory)(nil)
19 | }
20 |
--------------------------------------------------------------------------------
/transport/internet/tcp/sockopt_other.go:
--------------------------------------------------------------------------------
1 | //go:build !linux && !freebsd && !confonly
2 | // +build !linux,!freebsd,!confonly
3 |
4 | package tcp
5 |
6 | import (
7 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/net"
8 | "github.com/Shadowsocks-NET/v2ray-go/v4/transport/internet"
9 | )
10 |
11 | func GetOriginalDestination(conn internet.Connection) (net.Destination, error) {
12 | return net.Destination{}, nil
13 | }
14 |
--------------------------------------------------------------------------------
/common/bitmask/byte.go:
--------------------------------------------------------------------------------
1 | package bitmask
2 |
3 | // Byte is a bitmask in byte.
4 | type Byte byte
5 |
6 | // Has returns true if this bitmask contains another bitmask.
7 | func (b Byte) Has(bb Byte) bool {
8 | return (b & bb) != 0
9 | }
10 |
11 | func (b *Byte) Set(bb Byte) {
12 | *b |= bb
13 | }
14 |
15 | func (b *Byte) Clear(bb Byte) {
16 | *b &= ^bb
17 | }
18 |
19 | func (b *Byte) Toggle(bb Byte) {
20 | *b ^= bb
21 | }
22 |
--------------------------------------------------------------------------------
/common/log/log.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.common.log;
4 | option csharp_namespace = "V2Ray.Core.Common.Log";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/common/log";
6 | option java_package = "com.v2ray.core.common.log";
7 | option java_multiple_files = true;
8 |
9 | enum Severity {
10 | Unknown = 0;
11 | Error = 1;
12 | Warning = 2;
13 | Info = 3;
14 | Debug = 4;
15 | }
16 |
--------------------------------------------------------------------------------
/transport/internet/tcp/config.go:
--------------------------------------------------------------------------------
1 | //go:build !confonly
2 | // +build !confonly
3 |
4 | package tcp
5 |
6 | import (
7 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
8 | "github.com/Shadowsocks-NET/v2ray-go/v4/transport/internet"
9 | )
10 |
11 | const protocolName = "tcp"
12 |
13 | func init() {
14 | common.Must(internet.RegisterProtocolConfigCreator(protocolName, func() interface{} {
15 | return new(Config)
16 | }))
17 | }
18 |
--------------------------------------------------------------------------------
/transport/internet/headers/tls/config.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.transport.internet.headers.tls;
4 | option csharp_namespace = "V2Ray.Core.Transport.Internet.Headers.Tls";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/transport/internet/headers/tls";
6 | option java_package = "com.v2ray.core.transport.internet.headers.tls";
7 | option java_multiple_files = true;
8 |
9 | message PacketConfig {}
10 |
--------------------------------------------------------------------------------
/app/dispatcher/config.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.app.dispatcher;
4 | option csharp_namespace = "V2Ray.Core.App.Dispatcher";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/app/dispatcher";
6 | option java_package = "com.v2ray.core.app.dispatcher";
7 | option java_multiple_files = true;
8 |
9 | message SessionConfig {
10 | reserved 1;
11 | }
12 |
13 | message Config {
14 | SessionConfig settings = 1;
15 | }
16 |
--------------------------------------------------------------------------------
/proxy/vmess/vmess.go:
--------------------------------------------------------------------------------
1 | // Package vmess contains the implementation of VMess protocol and transportation.
2 | //
3 | // VMess contains both inbound and outbound connections. VMess inbound is usually used on servers
4 | // together with 'freedom' to talk to final destination, while VMess outbound is usually used on
5 | // clients with 'socks' for proxying.
6 | package vmess
7 |
8 | //go:generate go run github.com/Shadowsocks-NET/v2ray-go/v4/common/errors/errorgen
9 |
--------------------------------------------------------------------------------
/transport/internet/headers/wechat/config.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.transport.internet.headers.wechat;
4 | option csharp_namespace = "V2Ray.Core.Transport.Internet.Headers.Wechat";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/transport/internet/headers/wechat";
6 | option java_package = "com.v2ray.core.transport.internet.headers.wechat";
7 | option java_multiple_files = true;
8 |
9 | message VideoConfig {}
10 |
--------------------------------------------------------------------------------
/transport/internet/kcp/cryptreal.go:
--------------------------------------------------------------------------------
1 | package kcp
2 |
3 | import (
4 | "crypto/aes"
5 | "crypto/cipher"
6 | "crypto/sha256"
7 |
8 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
9 | )
10 |
11 | func NewAEADAESGCMBasedOnSeed(seed string) cipher.AEAD {
12 | hashedSeed := sha256.Sum256([]byte(seed))
13 | aesBlock := common.Must2(aes.NewCipher(hashedSeed[:16])).(cipher.Block)
14 | return common.Must2(cipher.NewGCM(aesBlock)).(cipher.AEAD)
15 | }
16 |
--------------------------------------------------------------------------------
/app/stats/config.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.app.stats;
4 | option csharp_namespace = "V2Ray.Core.App.Stats";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/app/stats";
6 | option java_package = "com.v2ray.core.app.stats";
7 | option java_multiple_files = true;
8 |
9 | message Config {}
10 |
11 | message ChannelConfig {
12 | bool Blocking = 1;
13 | int32 SubscriberLimit = 2;
14 | int32 BufferSize = 3;
15 | }
16 |
--------------------------------------------------------------------------------
/transport/internet/kcp/xor.go:
--------------------------------------------------------------------------------
1 | //go:build !amd64
2 | // +build !amd64
3 |
4 | package kcp
5 |
6 | // xorfwd performs XOR forwards in words, x[i] ^= x[i-4], i from 0 to len
7 | func xorfwd(x []byte) {
8 | for i := 4; i < len(x); i++ {
9 | x[i] ^= x[i-4]
10 | }
11 | }
12 |
13 | // xorbkd performs XOR backwords in words, x[i] ^= x[i-4], i from len to 0
14 | func xorbkd(x []byte) {
15 | for i := len(x) - 1; i >= 4; i-- {
16 | x[i] ^= x[i-4]
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/transport/internet/headers/utp/config.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.transport.internet.headers.utp;
4 | option csharp_namespace = "V2Ray.Core.Transport.Internet.Headers.Utp";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/transport/internet/headers/utp";
6 | option java_package = "com.v2ray.core.transport.internet.headers.utp";
7 | option java_multiple_files = true;
8 |
9 | message Config {
10 | uint32 version = 1;
11 | }
12 |
--------------------------------------------------------------------------------
/transport/internet/quic/pool.go:
--------------------------------------------------------------------------------
1 | //go:build !confonly
2 | // +build !confonly
3 |
4 | package quic
5 |
6 | import (
7 | "sync"
8 |
9 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/bytespool"
10 | )
11 |
12 | var pool *sync.Pool
13 |
14 | func init() {
15 | pool = bytespool.GetPool(2048)
16 | }
17 |
18 | func getBuffer() []byte {
19 | return pool.Get().([]byte)
20 | }
21 |
22 | func putBuffer(p []byte) {
23 | pool.Put(p) // nolint: staticcheck
24 | }
25 |
--------------------------------------------------------------------------------
/transport/internet/headers/wireguard/config.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.transport.internet.headers.wireguard;
4 | option csharp_namespace = "V2Ray.Core.Transport.Internet.Headers.Wireguard";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/transport/internet/headers/wireguard";
6 | option java_package = "com.v2ray.core.transport.internet.headers.wireguard";
7 | option java_multiple_files = true;
8 |
9 | message WireguardConfig {}
10 |
--------------------------------------------------------------------------------
/transport/internet/headers/noop/config.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.transport.internet.headers.noop;
4 | option csharp_namespace = "V2Ray.Core.Transport.Internet.Headers.Noop";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/transport/internet/headers/noop";
6 | option java_package = "com.v2ray.core.transport.internet.headers.noop";
7 | option java_multiple_files = true;
8 |
9 | message Config {}
10 |
11 | message ConnectionConfig {}
12 |
--------------------------------------------------------------------------------
/common/crypto/chacha20.go:
--------------------------------------------------------------------------------
1 | package crypto
2 |
3 | import (
4 | "crypto/cipher"
5 |
6 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/crypto/internal"
7 | )
8 |
9 | // NewChaCha20Stream creates a new Chacha20 encryption/descryption stream based on give key and IV.
10 | // Caller must ensure the length of key is 32 bytes, and length of IV is either 8 or 12 bytes.
11 | func NewChaCha20Stream(key []byte, iv []byte) cipher.Stream {
12 | return internal.NewChaCha20Stream(key, iv, 20)
13 | }
14 |
--------------------------------------------------------------------------------
/release/debian/v2ray@.service:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=V2Ray Service
3 | Documentation=https://www.v2fly.org/
4 | After=network.target nss-lookup.target
5 |
6 | [Service]
7 | User=nobody
8 | CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
9 | AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
10 | NoNewPrivileges=true
11 | ExecStart=/usr/bin/v2ray -config /etc/v2ray/%i.json
12 | Restart=on-failure
13 | RestartPreventExitStatus=23
14 |
15 | [Install]
16 | WantedBy=multi-user.target
17 |
--------------------------------------------------------------------------------
/release/debian/v2ray.service:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=V2Ray Service
3 | Documentation=https://www.v2fly.org/
4 | After=network.target nss-lookup.target
5 |
6 | [Service]
7 | User=nobody
8 | CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
9 | AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
10 | NoNewPrivileges=true
11 | ExecStart=/usr/bin/v2ray -config /etc/v2ray/config.json
12 | Restart=on-failure
13 | RestartPreventExitStatus=23
14 |
15 | [Install]
16 | WantedBy=multi-user.target
17 |
--------------------------------------------------------------------------------
/app/browserforwarder/config.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.app.browserforwarder;
4 |
5 | option csharp_namespace = "V2Ray.Core.App.Browserforwarder";
6 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/app/browserforwarder";
7 | option java_package = "com.v2ray.core.app.browserforwarder";
8 | option java_multiple_files = true;
9 |
10 | // Config is the settings for BrowserForwarder.
11 | message Config {
12 | string listen_addr = 1;
13 | int32 listen_port = 2;
14 | }
--------------------------------------------------------------------------------
/proxy/vmess/outbound/config.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.proxy.vmess.outbound;
4 | option csharp_namespace = "V2Ray.Core.Proxy.Vmess.Outbound";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/proxy/vmess/outbound";
6 | option java_package = "com.v2ray.core.proxy.vmess.outbound";
7 | option java_multiple_files = true;
8 |
9 | import "common/protocol/server_spec.proto";
10 |
11 | message Config {
12 | v2ray.core.common.protocol.ServerEndpoint Server = 1;
13 | }
14 |
--------------------------------------------------------------------------------
/transport/internet/udp/hub_other.go:
--------------------------------------------------------------------------------
1 | //go:build !linux && !freebsd
2 | // +build !linux,!freebsd
3 |
4 | package udp
5 |
6 | import (
7 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/net"
8 | )
9 |
10 | func RetrieveOriginalDest(oob []byte) net.Destination {
11 | return net.Destination{}
12 | }
13 |
14 | func ReadUDPMsg(conn *net.UDPConn, payload []byte, oob []byte) (int, int, int, *net.UDPAddr, error) {
15 | nBytes, addr, err := conn.ReadFromUDP(payload)
16 | return nBytes, 0, 0, addr, err
17 | }
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Binaries for programs and plugins
2 | *.exe
3 | *.exe~
4 | *.dll
5 | *.so
6 | *.dylib
7 |
8 | # Test binary, built with `go test -c`
9 | *.test
10 |
11 | # Output of the go coverage tool, specifically when used with LiteIDE
12 | *.out
13 |
14 | # Dependency directories (remove the comment below to include it)
15 | # vendor/
16 |
17 | *.DS_Store
18 | .idea
19 | *.zip
20 | *.tar.gz
21 | v2ray
22 | v2ctl
23 | mockgen
24 | vprotogen
25 | !infra/vprotogen/
26 | errorgen
27 | !common/errors/errorgen/
28 | *.dat
29 |
--------------------------------------------------------------------------------
/features/dns/fakedns.go:
--------------------------------------------------------------------------------
1 | package dns
2 |
3 | import (
4 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/net"
5 | "github.com/Shadowsocks-NET/v2ray-go/v4/features"
6 | )
7 |
8 | type FakeDNSEngine interface {
9 | features.Feature
10 | GetFakeIPForDomain(domain string) []net.Address
11 | GetDomainFromFakeDNS(ip net.Address) string
12 | }
13 |
14 | type FakeDNSEngineRev0 interface {
15 | FakeDNSEngine
16 | IsIPInIPPool(ip net.Address) bool
17 | GetFakeIPForDomain3(domain string, IPv4, IPv6 bool) []net.Address
18 | }
19 |
--------------------------------------------------------------------------------
/testing/servers/tcp/port.go:
--------------------------------------------------------------------------------
1 | package tcp
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/net"
4 |
5 | // PickPort returns an unused TCP port of the system.
6 | func PickPort() net.Port {
7 | listener := pickPort()
8 | defer listener.Close()
9 |
10 | addr := listener.Addr().(*net.TCPAddr)
11 | return net.Port(addr.Port)
12 | }
13 |
14 | func pickPort() net.Listener {
15 | listener, err := net.Listen("tcp4", "127.0.0.1:0")
16 | if err != nil {
17 | listener = pickPort()
18 | }
19 | return listener
20 | }
21 |
--------------------------------------------------------------------------------
/app/reverse/portal_test.go:
--------------------------------------------------------------------------------
1 | package reverse_test
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/Shadowsocks-NET/v2ray-go/v4/app/reverse"
7 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
8 | )
9 |
10 | func TestStaticPickerEmpty(t *testing.T) {
11 | picker, err := reverse.NewStaticMuxPicker()
12 | common.Must(err)
13 | worker, err := picker.PickAvailable()
14 | if err == nil {
15 | t.Error("expected error, but nil")
16 | }
17 | if worker != nil {
18 | t.Error("expected nil worker, but not nil")
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/common/protocol/context.go:
--------------------------------------------------------------------------------
1 | package protocol
2 |
3 | import (
4 | "context"
5 | )
6 |
7 | type key int
8 |
9 | const (
10 | requestKey key = iota
11 | )
12 |
13 | func ContextWithRequestHeader(ctx context.Context, request *RequestHeader) context.Context {
14 | return context.WithValue(ctx, requestKey, request)
15 | }
16 |
17 | func RequestHeaderFromContext(ctx context.Context) *RequestHeader {
18 | request := ctx.Value(requestKey)
19 | if request == nil {
20 | return nil
21 | }
22 | return request.(*RequestHeader)
23 | }
24 |
--------------------------------------------------------------------------------
/common/protocol/id_test.go:
--------------------------------------------------------------------------------
1 | package protocol_test
2 |
3 | import (
4 | "testing"
5 |
6 | . "github.com/Shadowsocks-NET/v2ray-go/v4/common/protocol"
7 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/uuid"
8 | )
9 |
10 | func TestIdEquals(t *testing.T) {
11 | id1 := NewID(uuid.New())
12 | id2 := NewID(id1.UUID())
13 |
14 | if !id1.Equals(id2) {
15 | t.Error("expected id1 to equal id2, but actually not")
16 | }
17 |
18 | if id1.String() != id2.String() {
19 | t.Error(id1.String(), " != ", id2.String())
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/common/protocol/time.go:
--------------------------------------------------------------------------------
1 | package protocol
2 |
3 | import (
4 | "time"
5 |
6 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/dice"
7 | )
8 |
9 | type Timestamp int64
10 |
11 | type TimestampGenerator func() Timestamp
12 |
13 | func NowTime() Timestamp {
14 | return Timestamp(time.Now().Unix())
15 | }
16 |
17 | func NewTimestampGenerator(base Timestamp, delta int) TimestampGenerator {
18 | return func() Timestamp {
19 | rangeInDelta := dice.Roll(delta*2) - delta
20 | return base + Timestamp(rangeInDelta)
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/proxy/dns/config.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.proxy.dns;
4 | option csharp_namespace = "V2Ray.Core.Proxy.Dns";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/proxy/dns";
6 | option java_package = "com.v2ray.core.proxy.dns";
7 | option java_multiple_files = true;
8 |
9 | import "common/net/destination.proto";
10 |
11 | message Config {
12 | // Server is the DNS server address. If specified, this address overrides the
13 | // original one.
14 | v2ray.core.common.net.Endpoint server = 1;
15 | }
16 |
--------------------------------------------------------------------------------
/common/net/network.go:
--------------------------------------------------------------------------------
1 | package net
2 |
3 | func (n Network) SystemString() string {
4 | switch n {
5 | case Network_TCP:
6 | return "tcp"
7 | case Network_UDP:
8 | return "udp"
9 | case Network_UNIX:
10 | return "unix"
11 | default:
12 | return "unknown"
13 | }
14 | }
15 |
16 | // HasNetwork returns true if the network list has a certain network.
17 | func HasNetwork(list []Network, network Network) bool {
18 | for _, value := range list {
19 | if value == network {
20 | return true
21 | }
22 | }
23 | return false
24 | }
25 |
--------------------------------------------------------------------------------
/proxy/blackhole/config.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.proxy.blackhole;
4 | option csharp_namespace = "V2Ray.Core.Proxy.Blackhole";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/proxy/blackhole";
6 | option java_package = "com.v2ray.core.proxy.blackhole";
7 | option java_multiple_files = true;
8 |
9 | import "common/serial/typed_message.proto";
10 |
11 | message NoneResponse {}
12 |
13 | message HTTPResponse {}
14 |
15 | message Config {
16 | v2ray.core.common.serial.TypedMessage response = 1;
17 | }
18 |
--------------------------------------------------------------------------------
/release/config/systemd/system/v2ray.service:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=V2Ray Service
3 | Documentation=https://www.v2fly.org/
4 | After=network.target nss-lookup.target
5 |
6 | [Service]
7 | User=v2ray
8 | Group=network
9 | CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
10 | AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
11 | NoNewPrivileges=true
12 | ExecStart=/usr/bin/v2ray -config /etc/v2ray/config.json -suppressTimestamps
13 | Restart=on-failure
14 | RestartPreventExitStatus=23
15 |
16 | [Install]
17 | WantedBy=multi-user.target
18 |
--------------------------------------------------------------------------------
/release/config/systemd/system/v2ray@.service:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=V2Ray Service
3 | Documentation=https://www.v2fly.org/
4 | After=network.target nss-lookup.target
5 |
6 | [Service]
7 | User=v2ray
8 | Group=network
9 | CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
10 | AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
11 | NoNewPrivileges=true
12 | ExecStart=/usr/bin/v2ray -config /etc/v2ray/%i.json -suppressTimestamps
13 | Restart=on-failure
14 | RestartPreventExitStatus=23
15 |
16 | [Install]
17 | WantedBy=multi-user.target
18 |
--------------------------------------------------------------------------------
/common/net/destination.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.common.net;
4 | option csharp_namespace = "V2Ray.Core.Common.Net";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/common/net";
6 | option java_package = "com.v2ray.core.common.net";
7 | option java_multiple_files = true;
8 |
9 | import "common/net/network.proto";
10 | import "common/net/address.proto";
11 |
12 | // Endpoint of a network connection.
13 | message Endpoint {
14 | Network network = 1;
15 | IPOrDomain address = 2;
16 | uint32 port = 3;
17 | }
18 |
--------------------------------------------------------------------------------
/common/net/network.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.common.net;
4 | option csharp_namespace = "V2Ray.Core.Common.Net";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/common/net";
6 | option java_package = "com.v2ray.core.common.net";
7 | option java_multiple_files = true;
8 |
9 | enum Network {
10 | Unknown = 0;
11 |
12 | RawTCP = 1 [deprecated = true];
13 | TCP = 2;
14 | UDP = 3;
15 | UNIX = 4;
16 | }
17 |
18 | // NetworkList is a list of Networks.
19 | message NetworkList { repeated Network network = 1; }
20 |
--------------------------------------------------------------------------------
/app/log/command/config.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.app.log.command;
4 | option csharp_namespace = "V2Ray.Core.App.Log.Command";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/app/log/command";
6 | option java_package = "com.v2ray.core.app.log.command";
7 | option java_multiple_files = true;
8 |
9 | message Config {}
10 |
11 | message RestartLoggerRequest {}
12 |
13 | message RestartLoggerResponse {}
14 |
15 | service LoggerService {
16 | rpc RestartLogger(RestartLoggerRequest) returns (RestartLoggerResponse) {}
17 | }
18 |
--------------------------------------------------------------------------------
/common/serial/typed_message_test.go:
--------------------------------------------------------------------------------
1 | package serial_test
2 |
3 | import (
4 | "testing"
5 |
6 | . "github.com/Shadowsocks-NET/v2ray-go/v4/common/serial"
7 | )
8 |
9 | func TestGetInstance(t *testing.T) {
10 | p, err := GetInstance("")
11 | if p != nil {
12 | t.Error("expected nil instance, but got ", p)
13 | }
14 | if err == nil {
15 | t.Error("expect non-nil error, but got nil")
16 | }
17 | }
18 |
19 | func TestConvertingNilMessage(t *testing.T) {
20 | x := ToTypedMessage(nil)
21 | if x != nil {
22 | t.Error("expect nil, but actually not")
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/testing/servers/udp/port.go:
--------------------------------------------------------------------------------
1 | package udp
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/net"
4 |
5 | // PickPort returns an unused UDP port of the system.
6 | func PickPort() net.Port {
7 | conn := pickPort()
8 | defer conn.Close()
9 |
10 | addr := conn.LocalAddr().(*net.UDPAddr)
11 | return net.Port(addr.Port)
12 | }
13 |
14 | func pickPort() *net.UDPConn {
15 | conn, err := net.ListenUDP("udp4", &net.UDPAddr{
16 | IP: net.LocalHostIP.IP(),
17 | Port: 0,
18 | })
19 | if err != nil {
20 | conn = pickPort()
21 | }
22 | return conn
23 | }
24 |
--------------------------------------------------------------------------------
/transport/internet/tcp/config.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.transport.internet.tcp;
4 | option csharp_namespace = "V2Ray.Core.Transport.Internet.Tcp";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/transport/internet/tcp";
6 | option java_package = "com.v2ray.core.transport.internet.tcp";
7 | option java_multiple_files = true;
8 |
9 | import "common/serial/typed_message.proto";
10 |
11 | message Config {
12 | reserved 1;
13 | v2ray.core.common.serial.TypedMessage header_settings = 2;
14 | bool accept_proxy_protocol = 3;
15 | }
16 |
--------------------------------------------------------------------------------
/common/protocol/headers.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.common.protocol;
4 | option csharp_namespace = "V2Ray.Core.Common.Protocol";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/common/protocol";
6 | option java_package = "com.v2ray.core.common.protocol";
7 | option java_multiple_files = true;
8 |
9 | enum SecurityType {
10 | UNKNOWN = 0;
11 | LEGACY = 1;
12 | AUTO = 2;
13 | AES128_GCM = 3;
14 | CHACHA20_POLY1305 = 4;
15 | NONE = 5;
16 | ZERO = 6;
17 | }
18 |
19 | message SecurityConfig {
20 | SecurityType type = 1;
21 | }
22 |
--------------------------------------------------------------------------------
/proxy/vmess/aead/kdf_test.go:
--------------------------------------------------------------------------------
1 | package aead
2 |
3 | import (
4 | "encoding/hex"
5 | "fmt"
6 | "testing"
7 |
8 | "github.com/stretchr/testify/assert"
9 | )
10 |
11 | func TestKDFValue(t *testing.T) {
12 | GeneratedKey := KDF([]byte("Demo Key for KDF Value Test"), "Demo Path for KDF Value Test", "Demo Path for KDF Value Test2", "Demo Path for KDF Value Test3")
13 | fmt.Println(hex.EncodeToString(GeneratedKey))
14 | assert.Equal(t, "53e9d7e1bd7bd25022b71ead07d8a596efc8a845c7888652fd684b4903dc8892", hex.EncodeToString(GeneratedKey), "Should generate expected KDF Value")
15 | }
16 |
--------------------------------------------------------------------------------
/common/peer/latency.go:
--------------------------------------------------------------------------------
1 | package peer
2 |
3 | import (
4 | "sync"
5 | )
6 |
7 | type Latency interface {
8 | Value() uint64
9 | }
10 |
11 | type HasLatency interface {
12 | ConnectionLatency() Latency
13 | HandshakeLatency() Latency
14 | }
15 |
16 | type AverageLatency struct {
17 | access sync.Mutex
18 | value uint64
19 | }
20 |
21 | func (al *AverageLatency) Update(newValue uint64) {
22 | al.access.Lock()
23 | defer al.access.Unlock()
24 |
25 | al.value = (al.value + newValue*2) / 3
26 | }
27 |
28 | func (al *AverageLatency) Value() uint64 {
29 | return al.value
30 | }
31 |
--------------------------------------------------------------------------------
/common/protocol/time_test.go:
--------------------------------------------------------------------------------
1 | package protocol_test
2 |
3 | import (
4 | "testing"
5 | "time"
6 |
7 | . "github.com/Shadowsocks-NET/v2ray-go/v4/common/protocol"
8 | )
9 |
10 | func TestGenerateRandomInt64InRange(t *testing.T) {
11 | base := time.Now().Unix()
12 | delta := 100
13 | generator := NewTimestampGenerator(Timestamp(base), delta)
14 |
15 | for i := 0; i < 100; i++ {
16 | val := int64(generator())
17 | if val > base+int64(delta) || val < base-int64(delta) {
18 | t.Error(val, " not between ", base-int64(delta), " and ", base+int64(delta))
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/common/serial/typed_message.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.common.serial;
4 | option csharp_namespace = "V2Ray.Core.Common.Serial";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/common/serial";
6 | option java_package = "com.v2ray.core.common.serial";
7 | option java_multiple_files = true;
8 |
9 | // TypedMessage is a serialized proto message along with its type name.
10 | message TypedMessage {
11 | // The name of the message type, retrieved from protobuf API.
12 | string type = 1;
13 | // Serialized proto message.
14 | bytes value = 2;
15 | }
16 |
--------------------------------------------------------------------------------
/common/protocol/server_spec.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.common.protocol;
4 | option csharp_namespace = "V2Ray.Core.Common.Protocol";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/common/protocol";
6 | option java_package = "com.v2ray.core.common.protocol";
7 | option java_multiple_files = true;
8 |
9 | import "common/net/address.proto";
10 | import "common/protocol/user.proto";
11 |
12 | message ServerEndpoint {
13 | v2ray.core.common.net.IPOrDomain address = 1;
14 | uint32 port = 2;
15 | repeated v2ray.core.common.protocol.User user = 3;
16 | }
17 |
--------------------------------------------------------------------------------
/proxy/freedom/config.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.proxy.freedom;
4 | option csharp_namespace = "V2Ray.Core.Proxy.Freedom";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/proxy/freedom";
6 | option java_package = "com.v2ray.core.proxy.freedom";
7 | option java_multiple_files = true;
8 |
9 | import "common/protocol/server_spec.proto";
10 |
11 | message DestinationOverride {
12 | v2ray.core.common.protocol.ServerEndpoint server = 1;
13 | }
14 |
15 | message Config {
16 | DestinationOverride destination_override = 3;
17 | uint32 user_level = 4;
18 | }
19 |
--------------------------------------------------------------------------------
/common/net/address.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.common.net;
4 | option csharp_namespace = "V2Ray.Core.Common.Net";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/common/net";
6 | option java_package = "com.v2ray.core.common.net";
7 | option java_multiple_files = true;
8 |
9 | // Address of a network host. It may be either an IP address or a domain
10 | // address.
11 | message IPOrDomain {
12 | oneof address {
13 | // IP address. Must by either 4 or 16 bytes.
14 | bytes ip = 1;
15 |
16 | // Domain address.
17 | string domain = 2;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/transport/internet/headers/srtp/config.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.transport.internet.headers.srtp;
4 | option csharp_namespace = "V2Ray.Core.Transport.Internet.Headers.Srtp";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/transport/internet/headers/srtp";
6 | option java_package = "com.v2ray.core.transport.internet.headers.srtp";
7 | option java_multiple_files = true;
8 |
9 | message Config {
10 | uint32 version = 1;
11 | bool padding = 2;
12 | bool extension = 3;
13 | uint32 csrc_count = 4;
14 | bool marker = 5;
15 | uint32 payload_type = 6;
16 | }
17 |
--------------------------------------------------------------------------------
/app/dns/fakedns/fakedns.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.app.dns.fakedns;
4 | option csharp_namespace = "V2Ray.Core.App.Dns.Fakedns";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/app/dns/fakedns";
6 | option java_package = "com.v2ray.core.app.dns.fakedns";
7 | option java_multiple_files = true;
8 |
9 | message FakeDnsPool{
10 | string ip_pool = 1; //CIDR of IP pool used as fake DNS IP
11 | int64 lruSize = 2; //Size of Pool for remembering relationship between domain name and IP address
12 | }
13 |
14 | message FakeDnsPoolMulti{
15 | repeated FakeDnsPool pools = 1;
16 | }
--------------------------------------------------------------------------------
/common/errors/multi_error.go:
--------------------------------------------------------------------------------
1 | package errors
2 |
3 | import (
4 | "strings"
5 | )
6 |
7 | type multiError []error
8 |
9 | func (e multiError) Error() string {
10 | var r strings.Builder
11 | r.WriteString("multierr: ")
12 | for _, err := range e {
13 | r.WriteString(err.Error())
14 | r.WriteString(" | ")
15 | }
16 | return r.String()
17 | }
18 |
19 | func Combine(maybeError ...error) error {
20 | var errs multiError
21 | for _, err := range maybeError {
22 | if err != nil {
23 | errs = append(errs, err)
24 | }
25 | }
26 | if len(errs) == 0 {
27 | return nil
28 | }
29 | return errs
30 | }
31 |
--------------------------------------------------------------------------------
/transport/internet/http/config.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.transport.internet.http;
4 | option csharp_namespace = "V2Ray.Core.Transport.Internet.Http";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/transport/internet/http";
6 | option java_package = "com.v2ray.core.transport.internet.http";
7 | option java_multiple_files = true;
8 |
9 | import "transport/internet/headers/http/config.proto";
10 |
11 | message Config {
12 | repeated string host = 1;
13 | string path = 2;
14 | string method = 3;
15 | repeated v2ray.core.transport.internet.headers.http.Header header = 4;
16 | }
17 |
--------------------------------------------------------------------------------
/common/strmatcher/full_matcher.go:
--------------------------------------------------------------------------------
1 | package strmatcher
2 |
3 | type FullMatcherGroup struct {
4 | matchers map[string][]uint32
5 | }
6 |
7 | func (g *FullMatcherGroup) Add(domain string, value uint32) {
8 | if g.matchers == nil {
9 | g.matchers = make(map[string][]uint32)
10 | }
11 |
12 | g.matchers[domain] = append(g.matchers[domain], value)
13 | }
14 |
15 | func (g *FullMatcherGroup) addMatcher(m fullMatcher, value uint32) {
16 | g.Add(string(m), value)
17 | }
18 |
19 | func (g *FullMatcherGroup) Match(str string) []uint32 {
20 | if g.matchers == nil {
21 | return nil
22 | }
23 |
24 | return g.matchers[str]
25 | }
26 |
--------------------------------------------------------------------------------
/transport/internet/system_dialer_other.go:
--------------------------------------------------------------------------------
1 | //go:build !linux
2 | // +build !linux
3 |
4 | package internet
5 |
6 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/net"
7 |
8 | func newUDPConnWrapper(conn *net.UDPConn, destAddr *net.UDPAddr, addressFamily net.AddressFamily, sockopt *SocketConfig) (*udpConnWrapper, error) {
9 | return &udpConnWrapper{
10 | UDPConn: conn,
11 | da: destAddr,
12 | }, nil
13 | }
14 |
15 | func (sockopt *SocketConfig) getBindInterfaceIP46() (bindInterfaceIP4, bindInterfaceIP6 []byte) {
16 | bindInterfaceIP4 = make([]byte, 4)
17 | bindInterfaceIP6 = make([]byte, 16)
18 | return
19 | }
20 |
--------------------------------------------------------------------------------
/transport/internet/quic/config.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.transport.internet.quic;
4 | option csharp_namespace = "V2Ray.Core.Transport.Internet.Quic";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/transport/internet/quic";
6 | option java_package = "com.v2ray.core.transport.internet.quic";
7 | option java_multiple_files = true;
8 |
9 | import "common/serial/typed_message.proto";
10 | import "common/protocol/headers.proto";
11 |
12 | message Config {
13 | string key = 1;
14 | v2ray.core.common.protocol.SecurityConfig security = 2;
15 | v2ray.core.common.serial.TypedMessage header = 3;
16 | }
17 |
--------------------------------------------------------------------------------
/common/net/port.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.common.net;
4 | option csharp_namespace = "V2Ray.Core.Common.Net";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/common/net";
6 | option java_package = "com.v2ray.core.common.net";
7 | option java_multiple_files = true;
8 |
9 | // PortRange represents a range of ports.
10 | message PortRange {
11 | // The port that this range starts from.
12 | uint32 From = 1;
13 | // The port that this range ends with (inclusive).
14 | uint32 To = 2;
15 | }
16 |
17 | // PortList is a list of ports.
18 | message PortList {
19 | repeated PortRange range = 1;
20 | }
21 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # To get started with Dependabot version updates, you'll need to specify which
2 | # package ecosystems to update and where the package manifests are located.
3 | # Please see the documentation for all configuration options:
4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5 |
6 | version: 2
7 | updates:
8 | - package-ecosystem: "gomod"
9 | directory: "/"
10 | schedule:
11 | interval: "daily"
12 | open-pull-requests-limit: 10
13 |
14 | - package-ecosystem: "github-actions"
15 | directory: "/"
16 | schedule:
17 | interval: "daily"
18 |
--------------------------------------------------------------------------------
/app/stats/counter.go:
--------------------------------------------------------------------------------
1 | //go:build !confonly
2 | // +build !confonly
3 |
4 | package stats
5 |
6 | import "sync/atomic"
7 |
8 | // Counter is an implementation of stats.Counter.
9 | type Counter struct {
10 | value int64
11 | }
12 |
13 | // Value implements stats.Counter.
14 | func (c *Counter) Value() int64 {
15 | return atomic.LoadInt64(&c.value)
16 | }
17 |
18 | // Set implements stats.Counter.
19 | func (c *Counter) Set(newValue int64) int64 {
20 | return atomic.SwapInt64(&c.value, newValue)
21 | }
22 |
23 | // Add implements stats.Counter.
24 | func (c *Counter) Add(delta int64) int64 {
25 | return atomic.AddInt64(&c.value, delta)
26 | }
27 |
--------------------------------------------------------------------------------
/infra/conf/geodata/geodataproto.go:
--------------------------------------------------------------------------------
1 | package geodata
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/app/router"
4 |
5 | //go:generate go run github.com/Shadowsocks-NET/v2ray-go/v4/common/errors/errorgen
6 |
7 | type LoaderImplementation interface {
8 | LoadSite(filename, list string) ([]*router.Domain, error)
9 | LoadIP(filename, country string) ([]*router.CIDR, error)
10 | }
11 |
12 | type Loader interface {
13 | LoaderImplementation
14 | LoadGeoSite(list string) ([]*router.Domain, error)
15 | LoadGeoSiteWithAttr(file string, siteWithAttr string) ([]*router.Domain, error)
16 | LoadGeoIP(country string) ([]*router.CIDR, error)
17 | }
18 |
--------------------------------------------------------------------------------
/transport/config.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.transport;
4 | option csharp_namespace = "V2Ray.Core.Transport";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/transport";
6 | option java_package = "com.v2ray.core.transport";
7 | option java_multiple_files = true;
8 |
9 | import "transport/internet/config.proto";
10 |
11 | // Global transport settings. This affects all type of connections that go
12 | // through V2Ray. Deprecated. Use each settings in StreamConfig.
13 | message Config {
14 | option deprecated = true;
15 | repeated v2ray.core.transport.internet.TransportConfig transport_settings = 1;
16 | }
17 |
--------------------------------------------------------------------------------
/common/signal/pubsub/pubsub_test.go:
--------------------------------------------------------------------------------
1 | package pubsub_test
2 |
3 | import (
4 | "testing"
5 |
6 | . "github.com/Shadowsocks-NET/v2ray-go/v4/common/signal/pubsub"
7 | )
8 |
9 | func TestPubsub(t *testing.T) {
10 | service := NewService()
11 |
12 | sub := service.Subscribe("a")
13 | service.Publish("a", 1)
14 |
15 | select {
16 | case v := <-sub.Wait():
17 | if v != 1 {
18 | t.Error("expected subscribed value 1, but got ", v)
19 | }
20 | default:
21 | t.Fail()
22 | }
23 |
24 | sub.Close()
25 | service.Publish("a", 2)
26 |
27 | select {
28 | case <-sub.Wait():
29 | t.Fail()
30 | default:
31 | }
32 |
33 | service.Cleanup()
34 | }
35 |
--------------------------------------------------------------------------------
/proxy/http/config.go:
--------------------------------------------------------------------------------
1 | package http
2 |
3 | import (
4 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/protocol"
5 | )
6 |
7 | func (a *Account) Equals(another protocol.Account) bool {
8 | if account, ok := another.(*Account); ok {
9 | return a.Username == account.Username
10 | }
11 | return false
12 | }
13 |
14 | func (a *Account) AsAccount() (protocol.Account, error) {
15 | return a, nil
16 | }
17 |
18 | func (sc *ServerConfig) HasAccount(username, password string) bool {
19 | if sc.Accounts == nil {
20 | return false
21 | }
22 |
23 | p, found := sc.Accounts[username]
24 | if !found {
25 | return false
26 | }
27 | return p == password
28 | }
29 |
--------------------------------------------------------------------------------
/app/log/config.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.app.log;
4 | option csharp_namespace = "V2Ray.Core.App.Log";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/app/log";
6 | option java_package = "com.v2ray.core.app.log";
7 | option java_multiple_files = true;
8 |
9 | import "common/log/log.proto";
10 |
11 | enum LogType {
12 | None = 0;
13 | Console = 1;
14 | File = 2;
15 | Event = 3;
16 | }
17 |
18 | message Config {
19 | LogType error_log_type = 1;
20 | v2ray.core.common.log.Severity error_log_level = 2;
21 | string error_log_path = 3;
22 |
23 | LogType access_log_type = 4;
24 | string access_log_path = 5;
25 | }
26 |
--------------------------------------------------------------------------------
/common/signal/semaphore/semaphore.go:
--------------------------------------------------------------------------------
1 | package semaphore
2 |
3 | // Instance is an implementation of semaphore.
4 | type Instance struct {
5 | token chan struct{}
6 | }
7 |
8 | // New create a new Semaphore with n permits.
9 | func New(n int) *Instance {
10 | s := &Instance{
11 | token: make(chan struct{}, n),
12 | }
13 | for i := 0; i < n; i++ {
14 | s.token <- struct{}{}
15 | }
16 | return s
17 | }
18 |
19 | // Wait returns a channel for acquiring a permit.
20 | func (s *Instance) Wait() <-chan struct{} {
21 | return s.token
22 | }
23 |
24 | // Signal releases a permit into the semaphore.
25 | func (s *Instance) Signal() {
26 | s.token <- struct{}{}
27 | }
28 |
--------------------------------------------------------------------------------
/common/protocol/user.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.common.protocol;
4 | option csharp_namespace = "V2Ray.Core.Common.Protocol";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/common/protocol";
6 | option java_package = "com.v2ray.core.common.protocol";
7 | option java_multiple_files = true;
8 |
9 | import "common/serial/typed_message.proto";
10 |
11 | // User is a generic user for all procotols.
12 | message User {
13 | uint32 level = 1;
14 | string email = 2;
15 |
16 | // Protocol specific account information. Must be the account proto in one of
17 | // the proxies.
18 | v2ray.core.common.serial.TypedMessage account = 3;
19 | }
20 |
--------------------------------------------------------------------------------
/infra/conf/browser_forwarder.go:
--------------------------------------------------------------------------------
1 | package conf
2 |
3 | import (
4 | "strings"
5 |
6 | "github.com/golang/protobuf/proto"
7 |
8 | "github.com/Shadowsocks-NET/v2ray-go/v4/app/browserforwarder"
9 | )
10 |
11 | type BrowserForwarderConfig struct {
12 | ListenAddr string `json:"listenAddr"`
13 | ListenPort int32 `json:"listenPort"`
14 | }
15 |
16 | func (b *BrowserForwarderConfig) Build() (proto.Message, error) {
17 | b.ListenAddr = strings.TrimSpace(b.ListenAddr)
18 | if b.ListenAddr != "" && b.ListenPort == 0 {
19 | b.ListenPort = 54321
20 | }
21 | return &browserforwarder.Config{
22 | ListenAddr: b.ListenAddr,
23 | ListenPort: b.ListenPort,
24 | }, nil
25 | }
26 |
--------------------------------------------------------------------------------
/infra/conf/observatory.go:
--------------------------------------------------------------------------------
1 | package conf
2 |
3 | import (
4 | "github.com/golang/protobuf/proto"
5 |
6 | "github.com/Shadowsocks-NET/v2ray-go/v4/app/observatory"
7 | "github.com/Shadowsocks-NET/v2ray-go/v4/infra/conf/cfgcommon/duration"
8 | )
9 |
10 | type ObservatoryConfig struct {
11 | SubjectSelector []string `json:"subjectSelector"`
12 | ProbeURL string `json:"probeURL"`
13 | ProbeInterval duration.Duration `json:"probeInterval"`
14 | }
15 |
16 | func (o *ObservatoryConfig) Build() (proto.Message, error) {
17 | return &observatory.Config{SubjectSelector: o.SubjectSelector, ProbeUrl: o.ProbeURL, ProbeInterval: int64(o.ProbeInterval)}, nil
18 | }
19 |
--------------------------------------------------------------------------------
/infra/control/uuid.go:
--------------------------------------------------------------------------------
1 | package control
2 |
3 | import (
4 | "fmt"
5 |
6 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
7 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/uuid"
8 | )
9 |
10 | type UUIDCommand struct{}
11 |
12 | func (c *UUIDCommand) Name() string {
13 | return "uuid"
14 | }
15 |
16 | func (c *UUIDCommand) Description() Description {
17 | return Description{
18 | Short: "Generate new UUID",
19 | Usage: []string{"v2ctl uuid"},
20 | }
21 | }
22 |
23 | func (c *UUIDCommand) Execute([]string) error {
24 | u := uuid.New()
25 | fmt.Println(u.String())
26 | return nil
27 | }
28 |
29 | func init() {
30 | common.Must(RegisterCommand(&UUIDCommand{}))
31 | }
32 |
--------------------------------------------------------------------------------
/proxy/vmess/encoding/encoding.go:
--------------------------------------------------------------------------------
1 | package encoding
2 |
3 | import (
4 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/net"
5 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/protocol"
6 | )
7 |
8 | //go:generate go run github.com/Shadowsocks-NET/v2ray-go/v4/common/errors/errorgen
9 |
10 | const (
11 | Version = byte(1)
12 | )
13 |
14 | var addrParser = protocol.NewAddressParser(
15 | protocol.AddressFamilyByte(byte(protocol.AddressTypeIPv4), net.AddressFamilyIPv4),
16 | protocol.AddressFamilyByte(byte(protocol.AddressTypeDomain), net.AddressFamilyDomain),
17 | protocol.AddressFamilyByte(byte(protocol.AddressTypeIPv6), net.AddressFamilyIPv6),
18 | protocol.PortThenAddress(),
19 | )
20 |
--------------------------------------------------------------------------------
/common/protocol/bittorrent/bittorrent.go:
--------------------------------------------------------------------------------
1 | package bittorrent
2 |
3 | import (
4 | "errors"
5 |
6 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
7 | )
8 |
9 | type SniffHeader struct{}
10 |
11 | func (h *SniffHeader) Protocol() string {
12 | return "bittorrent"
13 | }
14 |
15 | func (h *SniffHeader) Domain() string {
16 | return ""
17 | }
18 |
19 | var errNotBittorrent = errors.New("not bittorrent header")
20 |
21 | func SniffBittorrent(b []byte) (*SniffHeader, error) {
22 | if len(b) < 20 {
23 | return nil, common.ErrNoClue
24 | }
25 |
26 | if b[0] == 19 && string(b[1:20]) == "BitTorrent protocol" {
27 | return &SniffHeader{}, nil
28 | }
29 |
30 | return nil, errNotBittorrent
31 | }
32 |
--------------------------------------------------------------------------------
/app/observatory/explainErrors.go:
--------------------------------------------------------------------------------
1 | package observatory
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
4 |
5 | type errorCollector struct {
6 | errors *errors.Error
7 | }
8 |
9 | func (e *errorCollector) SubmitError(err error) {
10 | if e.errors == nil {
11 | e.errors = newError("underlying connection error").Base(err)
12 | return
13 | }
14 | e.errors = e.errors.Base(newError("underlying connection error").Base(err))
15 | }
16 |
17 | func newErrorCollector() *errorCollector {
18 | return &errorCollector{}
19 | }
20 |
21 | func (e *errorCollector) UnderlyingError() error {
22 | if e.errors == nil {
23 | return newError("failed to produce report")
24 | }
25 | return e.errors
26 | }
27 |
--------------------------------------------------------------------------------
/proxy/socks/config.go:
--------------------------------------------------------------------------------
1 | //go:build !confonly
2 | // +build !confonly
3 |
4 | package socks
5 |
6 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/protocol"
7 |
8 | func (a *Account) Equals(another protocol.Account) bool {
9 | if account, ok := another.(*Account); ok {
10 | return a.Username == account.Username
11 | }
12 | return false
13 | }
14 |
15 | func (a *Account) AsAccount() (protocol.Account, error) {
16 | return a, nil
17 | }
18 |
19 | func (c *ServerConfig) HasAccount(username, password string) bool {
20 | if c.Accounts == nil {
21 | return false
22 | }
23 | storedPassed, found := c.Accounts[username]
24 | if !found {
25 | return false
26 | }
27 | return storedPassed == password
28 | }
29 |
--------------------------------------------------------------------------------
/proxy/vmess/inbound/config.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.proxy.vmess.inbound;
4 | option csharp_namespace = "V2Ray.Core.Proxy.Vmess.Inbound";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/proxy/vmess/inbound";
6 | option java_package = "com.v2ray.core.proxy.vmess.inbound";
7 | option java_multiple_files = true;
8 |
9 | import "common/protocol/user.proto";
10 |
11 | message DetourConfig {
12 | string to = 1;
13 | }
14 |
15 | message DefaultConfig {
16 | uint32 level = 2;
17 | }
18 |
19 | message Config {
20 | repeated v2ray.core.common.protocol.User user = 1;
21 | DefaultConfig default = 2;
22 | DetourConfig detour = 3;
23 | bool secure_encryption_only = 4;
24 | }
25 |
--------------------------------------------------------------------------------
/common/mux/frame_test.go:
--------------------------------------------------------------------------------
1 | package mux_test
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
7 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/buf"
8 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/mux"
9 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/net"
10 | )
11 |
12 | func BenchmarkFrameWrite(b *testing.B) {
13 | frame := mux.FrameMetadata{
14 | Target: net.TCPDestination(net.DomainAddress("www.v2fly.org"), net.Port(80)),
15 | SessionID: 1,
16 | SessionStatus: mux.SessionStatusNew,
17 | }
18 | writer := buf.New()
19 | defer writer.Release()
20 |
21 | for i := 0; i < b.N; i++ {
22 | common.Must(frame.WriteTo(writer))
23 | writer.Clear()
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/proxy/vmess/encoding/auth_test.go:
--------------------------------------------------------------------------------
1 | package encoding_test
2 |
3 | import (
4 | "crypto/rand"
5 | "testing"
6 |
7 | "github.com/google/go-cmp/cmp"
8 |
9 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
10 | . "github.com/Shadowsocks-NET/v2ray-go/v4/proxy/vmess/encoding"
11 | )
12 |
13 | func TestFnvAuth(t *testing.T) {
14 | fnvAuth := new(FnvAuthenticator)
15 |
16 | expectedText := make([]byte, 256)
17 | _, err := rand.Read(expectedText)
18 | common.Must(err)
19 |
20 | buffer := make([]byte, 512)
21 | b := fnvAuth.Seal(buffer[:0], nil, expectedText, nil)
22 | b, err = fnvAuth.Open(buffer[:0], nil, b, nil)
23 | common.Must(err)
24 | if r := cmp.Diff(b, expectedText); r != "" {
25 | t.Error(r)
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/transport/internet/headers/wechat/wechat_test.go:
--------------------------------------------------------------------------------
1 | package wechat_test
2 |
3 | import (
4 | "context"
5 | "testing"
6 |
7 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
8 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/buf"
9 | . "github.com/Shadowsocks-NET/v2ray-go/v4/transport/internet/headers/wechat"
10 | )
11 |
12 | func TestUTPWrite(t *testing.T) {
13 | videoRaw, err := NewVideoChat(context.Background(), &VideoConfig{})
14 | common.Must(err)
15 |
16 | video := videoRaw.(*VideoChat)
17 |
18 | payload := buf.New()
19 | video.Serialize(payload.Extend(video.Size()))
20 |
21 | if payload.Len() != video.Size() {
22 | t.Error("expected payload size ", video.Size(), " but got ", payload.Len())
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/proxy/vmess/account.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.proxy.vmess;
4 | option csharp_namespace = "V2Ray.Core.Proxy.Vmess";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/proxy/vmess";
6 | option java_package = "com.v2ray.core.proxy.vmess";
7 | option java_multiple_files = true;
8 |
9 | import "common/protocol/headers.proto";
10 |
11 | message Account {
12 | // ID of the account, in the form of a UUID, e.g.,
13 | // "66ad4540-b58c-4ad2-9926-ea63445a9b57".
14 | string id = 1;
15 | // Security settings. Only applies to client side.
16 | v2ray.core.common.protocol.SecurityConfig security_settings = 3;
17 | // Define tests enabled for this account
18 | string tests_enabled = 4;
19 | }
20 |
--------------------------------------------------------------------------------
/app/dispatcher/stats.go:
--------------------------------------------------------------------------------
1 | //go:build !confonly
2 | // +build !confonly
3 |
4 | package dispatcher
5 |
6 | import (
7 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
8 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/buf"
9 | "github.com/Shadowsocks-NET/v2ray-go/v4/features/stats"
10 | )
11 |
12 | type SizeStatWriter struct {
13 | Counter stats.Counter
14 | Writer buf.Writer
15 | }
16 |
17 | func (w *SizeStatWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
18 | w.Counter.Add(int64(mb.Len()))
19 | return w.Writer.WriteMultiBuffer(mb)
20 | }
21 |
22 | func (w *SizeStatWriter) Close() error {
23 | return common.Close(w.Writer)
24 | }
25 |
26 | func (w *SizeStatWriter) Interrupt() {
27 | common.Interrupt(w.Writer)
28 | }
29 |
--------------------------------------------------------------------------------
/annotations.go:
--------------------------------------------------------------------------------
1 | package core
2 |
3 | // Annotation is a concept in V2Ray. This struct is only for documentation. It is not used anywhere.
4 | // Annotations begin with "v2ray:" in comment, as metadata of functions or types.
5 | type Annotation struct {
6 | // API is for types or functions that can be used in other libs. Possible values are:
7 | //
8 | // * v2ray:api:beta for types or functions that are ready for use, but maybe changed in the future.
9 | // * v2ray:api:stable for types or functions with guarantee of backward compatibility.
10 | // * v2ray:api:deprecated for types or functions that should not be used anymore.
11 | //
12 | // Types or functions without api annotation should not be used externally.
13 | API string
14 | }
15 |
--------------------------------------------------------------------------------
/features/policy/default.go:
--------------------------------------------------------------------------------
1 | package policy
2 |
3 | // DefaultManager is the implementation of the Manager.
4 | type DefaultManager struct{}
5 |
6 | // Type implements common.HasType.
7 | func (DefaultManager) Type() interface{} {
8 | return ManagerType()
9 | }
10 |
11 | // ForLevel implements Manager.
12 | func (DefaultManager) ForLevel(level uint32) Session {
13 | return SessionDefault()
14 | }
15 |
16 | // ForSystem implements Manager.
17 | func (DefaultManager) ForSystem() System {
18 | return System{}
19 | }
20 |
21 | // Start implements common.Runnable.
22 | func (DefaultManager) Start() error {
23 | return nil
24 | }
25 |
26 | // Close implements common.Closable.
27 | func (DefaultManager) Close() error {
28 | return nil
29 | }
30 |
--------------------------------------------------------------------------------
/infra/conf/cfgcommon/duration/duration.go:
--------------------------------------------------------------------------------
1 | package duration
2 |
3 | import (
4 | "encoding/json"
5 | "fmt"
6 | "time"
7 | )
8 |
9 | type Duration int64
10 |
11 | func (d *Duration) MarshalJSON() ([]byte, error) {
12 | dr := time.Duration(*d)
13 | return json.Marshal(dr.String())
14 | }
15 |
16 | func (d *Duration) UnmarshalJSON(b []byte) error {
17 | var v interface{}
18 | if err := json.Unmarshal(b, &v); err != nil {
19 | return err
20 | }
21 | switch value := v.(type) {
22 | case string:
23 | var err error
24 | dr, err := time.ParseDuration(value)
25 | if err != nil {
26 | return err
27 | }
28 | *d = Duration(dr)
29 | return nil
30 | default:
31 | return fmt.Errorf("invalid duration: %v", v)
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/transport/internet/headers/wireguard/wireguard.go:
--------------------------------------------------------------------------------
1 | package wireguard
2 |
3 | import (
4 | "context"
5 |
6 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
7 | )
8 |
9 | type Wireguard struct{}
10 |
11 | func (Wireguard) Size() int32 {
12 | return 4
13 | }
14 |
15 | // Serialize implements PacketHeader.
16 | func (Wireguard) Serialize(b []byte) {
17 | b[0] = 0x04
18 | b[1] = 0x00
19 | b[2] = 0x00
20 | b[3] = 0x00
21 | }
22 |
23 | // NewWireguard returns a new VideoChat instance based on given config.
24 | func NewWireguard(ctx context.Context, config interface{}) (interface{}, error) {
25 | return Wireguard{}, nil
26 | }
27 |
28 | func init() {
29 | common.Must(common.RegisterConfig((*WireguardConfig)(nil), NewWireguard))
30 | }
31 |
--------------------------------------------------------------------------------
/transport/pipe/writer.go:
--------------------------------------------------------------------------------
1 | package pipe
2 |
3 | import (
4 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/buf"
5 | )
6 |
7 | // Writer is a buf.Writer that writes data into a pipe.
8 | type Writer struct {
9 | pipe *pipe
10 | }
11 |
12 | // WriteMultiBuffer implements buf.Writer.
13 | func (w *Writer) WriteMultiBuffer(mb buf.MultiBuffer) error {
14 | return w.pipe.WriteMultiBuffer(mb)
15 | }
16 |
17 | // Close implements io.Closer. After the pipe is closed, writing to the pipe will return io.ErrClosedPipe, while reading will return io.EOF.
18 | func (w *Writer) Close() error {
19 | return w.pipe.Close()
20 | }
21 |
22 | // Interrupt implements common.Interruptible.
23 | func (w *Writer) Interrupt() {
24 | w.pipe.Interrupt()
25 | }
26 |
--------------------------------------------------------------------------------
/common/buf/readv_unix.go:
--------------------------------------------------------------------------------
1 | //go:build illumos
2 | // +build illumos
3 |
4 | package buf
5 |
6 | import "golang.org/x/sys/unix"
7 |
8 | type unixReader struct {
9 | iovs [][]byte
10 | }
11 |
12 | func (r *unixReader) Init(bs []*Buffer) {
13 | iovs := r.iovs
14 | if iovs == nil {
15 | iovs = make([][]byte, 0, len(bs))
16 | }
17 | for _, b := range bs {
18 | iovs = append(iovs, b.v)
19 | }
20 | r.iovs = iovs
21 | }
22 |
23 | func (r *unixReader) Read(fd uintptr) int32 {
24 | n, e := unix.Readv(int(fd), r.iovs)
25 | if e != nil {
26 | return -1
27 | }
28 | return int32(n)
29 | }
30 |
31 | func (r *unixReader) Clear() {
32 | r.iovs = r.iovs[:0]
33 | }
34 |
35 | func newMultiReader() multiReader {
36 | return &unixReader{}
37 | }
38 |
--------------------------------------------------------------------------------
/proxy/blackhole/config_test.go:
--------------------------------------------------------------------------------
1 | package blackhole_test
2 |
3 | import (
4 | "bufio"
5 | "net/http"
6 | "testing"
7 |
8 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
9 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/buf"
10 | . "github.com/Shadowsocks-NET/v2ray-go/v4/proxy/blackhole"
11 | )
12 |
13 | func TestHTTPResponse(t *testing.T) {
14 | buffer := buf.New()
15 |
16 | httpResponse := new(HTTPResponse)
17 | httpResponse.WriteTo(buf.NewWriter(buffer))
18 |
19 | reader := bufio.NewReader(buffer)
20 | response, err := http.ReadResponse(reader, nil)
21 | common.Must(err)
22 | defer response.Body.Close()
23 |
24 | if response.StatusCode != 403 {
25 | t.Error("expected status code 403, but got ", response.StatusCode)
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/transport/internet/sockopt_other.go:
--------------------------------------------------------------------------------
1 | //go:build js || dragonfly || netbsd || openbsd || solaris
2 | // +build js dragonfly netbsd openbsd solaris
3 |
4 | package internet
5 |
6 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/net"
7 |
8 | func applyOutboundSocketOptions(network string, address string, fd uintptr, config *SocketConfig, dest net.Destination) error {
9 | return nil
10 | }
11 |
12 | func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig) error {
13 | return nil
14 | }
15 |
16 | func bindAddr(fd uintptr, ip []byte, port uint32) error {
17 | return nil
18 | }
19 |
20 | func setReuseAddr(fd uintptr) error {
21 | return nil
22 | }
23 |
24 | func setReusePort(fd uintptr) error {
25 | return nil
26 | }
27 |
--------------------------------------------------------------------------------
/common/log/log_test.go:
--------------------------------------------------------------------------------
1 | package log_test
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/google/go-cmp/cmp"
7 |
8 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/log"
9 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/net"
10 | )
11 |
12 | type testLogger struct {
13 | value string
14 | }
15 |
16 | func (l *testLogger) Handle(msg log.Message) {
17 | l.value = msg.String()
18 | }
19 |
20 | func TestLogRecord(t *testing.T) {
21 | var logger testLogger
22 | log.RegisterHandler(&logger)
23 |
24 | ip := "8.8.8.8"
25 | log.Record(&log.GeneralMessage{
26 | Severity: log.Severity_Error,
27 | Content: net.ParseAddress(ip),
28 | })
29 |
30 | if diff := cmp.Diff("[Error] "+ip, logger.value); diff != "" {
31 | t.Error(diff)
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/app/dns/nameserver_local_test.go:
--------------------------------------------------------------------------------
1 | package dns_test
2 |
3 | import (
4 | "context"
5 | "testing"
6 | "time"
7 |
8 | . "github.com/Shadowsocks-NET/v2ray-go/v4/app/dns"
9 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
10 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/net"
11 | "github.com/Shadowsocks-NET/v2ray-go/v4/features/dns"
12 | )
13 |
14 | func TestLocalNameServer(t *testing.T) {
15 | s := NewLocalNameServer()
16 | ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
17 | ips, err := s.QueryIP(ctx, "google.com", net.IP{}, dns.IPOption{
18 | IPv4Enable: true,
19 | IPv6Enable: true,
20 | }, false)
21 | cancel()
22 | common.Must(err)
23 | if len(ips) == 0 {
24 | t.Error("expect some ips, but got 0")
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/observatory/command/command.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.app.observatory.command;
4 | option csharp_namespace = "V2Ray.Core.App.Observatory.Command";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/app/observatory/command";
6 | option java_package = "com.v2ray.core.app.observatory.command";
7 | option java_multiple_files = true;
8 |
9 | import "app/observatory/config.proto";
10 |
11 | message GetOutboundStatusRequest {
12 | }
13 |
14 | message GetOutboundStatusResponse {
15 | v2ray.core.app.observatory.ObservationResult status = 1;
16 | }
17 |
18 | service ObservatoryService {
19 | rpc GetOutboundStatus(GetOutboundStatusRequest)
20 | returns (GetOutboundStatusResponse) {}
21 | }
22 |
23 |
24 | message Config {}
--------------------------------------------------------------------------------
/transport/internet/headers/utp/utp_test.go:
--------------------------------------------------------------------------------
1 | package utp_test
2 |
3 | import (
4 | "context"
5 | "testing"
6 |
7 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
8 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/buf"
9 | . "github.com/Shadowsocks-NET/v2ray-go/v4/transport/internet/headers/utp"
10 | )
11 |
12 | func TestUTPWrite(t *testing.T) {
13 | content := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g'}
14 | utpRaw, err := New(context.Background(), &Config{})
15 | common.Must(err)
16 |
17 | utp := utpRaw.(*UTP)
18 |
19 | payload := buf.New()
20 | utp.Serialize(payload.Extend(utp.Size()))
21 | payload.Write(content)
22 |
23 | if payload.Len() != int32(len(content))+utp.Size() {
24 | t.Error("unexpected payload length: ", payload.Len())
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/common/signal/notifier.go:
--------------------------------------------------------------------------------
1 | package signal
2 |
3 | // Notifier is a utility for notifying changes. The change producer may notify changes multiple time, and the consumer may get notified asynchronously.
4 | type Notifier struct {
5 | c chan struct{}
6 | }
7 |
8 | // NewNotifier creates a new Notifier.
9 | func NewNotifier() *Notifier {
10 | return &Notifier{
11 | c: make(chan struct{}, 1),
12 | }
13 | }
14 |
15 | // Signal signals a change, usually by producer. This method never blocks.
16 | func (n *Notifier) Signal() {
17 | select {
18 | case n.c <- struct{}{}:
19 | default:
20 | }
21 | }
22 |
23 | // Wait returns a channel for waiting for changes. The returned channel never gets closed.
24 | func (n *Notifier) Wait() <-chan struct{} {
25 | return n.c
26 | }
27 |
--------------------------------------------------------------------------------
/transport/internet/system_listener_test.go:
--------------------------------------------------------------------------------
1 | package internet_test
2 |
3 | import (
4 | "context"
5 | "net"
6 | "testing"
7 |
8 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
9 | "github.com/Shadowsocks-NET/v2ray-go/v4/transport/internet"
10 | )
11 |
12 | func TestRegisterListenerController(t *testing.T) {
13 | var gotFd uintptr
14 |
15 | common.Must(internet.RegisterListenerController(func(network string, addr string, fd uintptr) error {
16 | gotFd = fd
17 | return nil
18 | }))
19 |
20 | conn, err := internet.ListenSystemPacket(context.Background(), &net.UDPAddr{
21 | IP: net.IPv4zero,
22 | }, nil)
23 | common.Must(err)
24 | common.Must(conn.Close())
25 |
26 | if gotFd == 0 {
27 | t.Error("expected none-zero fd, but actually 0")
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/app/reverse/config.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.app.reverse;
4 | option csharp_namespace = "V2Ray.Core.Proxy.Reverse";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/app/reverse";
6 | option java_package = "com.v2ray.core.proxy.reverse";
7 | option java_multiple_files = true;
8 |
9 | message Control {
10 | enum State {
11 | ACTIVE = 0;
12 | DRAIN = 1;
13 | }
14 |
15 | State state = 1;
16 | bytes random = 99;
17 | }
18 |
19 | message BridgeConfig {
20 | string tag = 1;
21 | string domain = 2;
22 | }
23 |
24 | message PortalConfig {
25 | string tag = 1;
26 | string domain = 2;
27 | }
28 |
29 | message Config {
30 | repeated BridgeConfig bridge_config = 1;
31 | repeated PortalConfig portal_config = 2;
32 | }
33 |
--------------------------------------------------------------------------------
/common/serial/string.go:
--------------------------------------------------------------------------------
1 | package serial
2 |
3 | import (
4 | "fmt"
5 | "strings"
6 | )
7 |
8 | // ToString serialize an arbitrary value into string.
9 | func ToString(v interface{}) string {
10 | if v == nil {
11 | return ""
12 | }
13 |
14 | switch value := v.(type) {
15 | case string:
16 | return value
17 | case *string:
18 | return *value
19 | case fmt.Stringer:
20 | return value.String()
21 | case error:
22 | return value.Error()
23 | default:
24 | return fmt.Sprintf("%+v", value)
25 | }
26 | }
27 |
28 | // Concat concatenates all input into a single string.
29 | func Concat(v ...interface{}) string {
30 | builder := strings.Builder{}
31 | for _, value := range v {
32 | builder.WriteString(ToString(value))
33 | }
34 | return builder.String()
35 | }
36 |
--------------------------------------------------------------------------------
/common/platform/windows.go:
--------------------------------------------------------------------------------
1 | //go:build windows
2 | // +build windows
3 |
4 | package platform
5 |
6 | import "path/filepath"
7 |
8 | func ExpandEnv(s string) string {
9 | // TODO
10 | return s
11 | }
12 |
13 | func LineSeparator() string {
14 | return "\r\n"
15 | }
16 |
17 | func GetToolLocation(file string) string {
18 | const name = "v2ray.location.tool"
19 | toolPath := EnvFlag{Name: name, AltName: NormalizeEnvName(name)}.GetValue(getExecutableDir)
20 | return filepath.Join(toolPath, file+".exe")
21 | }
22 |
23 | // GetAssetLocation search for `file` in the excutable dir
24 | func GetAssetLocation(file string) string {
25 | const name = "v2ray.location.asset"
26 | assetPath := NewEnvFlag(name).GetValue(getExecutableDir)
27 | return filepath.Join(assetPath, file)
28 | }
29 |
--------------------------------------------------------------------------------
/common/antireplay/bloomring.go:
--------------------------------------------------------------------------------
1 | package antireplay
2 |
3 | import (
4 | "sync"
5 |
6 | ss_bloomring "github.com/v2fly/ss-bloomring"
7 | )
8 |
9 | type BloomRing struct {
10 | *ss_bloomring.BloomRing
11 | lock *sync.Mutex
12 | }
13 |
14 | func (b BloomRing) Interval() int64 {
15 | return 9999999
16 | }
17 |
18 | func (b BloomRing) Check(sum []byte) bool {
19 | b.lock.Lock()
20 | defer b.lock.Unlock()
21 | if b.Test(sum) {
22 | return false
23 | }
24 | b.Add(sum)
25 | return true
26 | }
27 |
28 | func NewBloomRing() BloomRing {
29 | const (
30 | DefaultSFCapacity = 1e6
31 | // FalsePositiveRate
32 | DefaultSFFPR = 1e-6
33 | DefaultSFSlot = 10
34 | )
35 | return BloomRing{ss_bloomring.NewBloomRing(DefaultSFSlot, DefaultSFCapacity, DefaultSFFPR), &sync.Mutex{}}
36 | }
37 |
--------------------------------------------------------------------------------
/app/commander/service.go:
--------------------------------------------------------------------------------
1 | //go:build !confonly
2 | // +build !confonly
3 |
4 | package commander
5 |
6 | import (
7 | "context"
8 |
9 | "google.golang.org/grpc"
10 | "google.golang.org/grpc/reflection"
11 |
12 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
13 | )
14 |
15 | // Service is a Commander service.
16 | type Service interface {
17 | // Register registers the service itself to a gRPC server.
18 | Register(*grpc.Server)
19 | }
20 |
21 | type reflectionService struct{}
22 |
23 | func (r reflectionService) Register(s *grpc.Server) {
24 | reflection.Register(s)
25 | }
26 |
27 | func init() {
28 | common.Must(common.RegisterConfig((*ReflectionConfig)(nil), func(ctx context.Context, cfg interface{}) (interface{}, error) {
29 | return reflectionService{}, nil
30 | }))
31 | }
32 |
--------------------------------------------------------------------------------
/testing/scenarios/common_regular.go:
--------------------------------------------------------------------------------
1 | //go:build !coverage
2 | // +build !coverage
3 |
4 | package scenarios
5 |
6 | import (
7 | "bytes"
8 | "fmt"
9 | "os"
10 | "os/exec"
11 | )
12 |
13 | func BuildV2Ray() error {
14 | genTestBinaryPath()
15 | if _, err := os.Stat(testBinaryPath); err == nil {
16 | return nil
17 | }
18 |
19 | fmt.Printf("Building V2Ray into path (%s)\n", testBinaryPath)
20 | cmd := exec.Command("go", "build", "-o="+testBinaryPath, GetSourcePath())
21 | return cmd.Run()
22 | }
23 |
24 | func RunV2RayProtobuf(config []byte) *exec.Cmd {
25 | genTestBinaryPath()
26 | proc := exec.Command(testBinaryPath, "-config=stdin:", "-format=pb")
27 | proc.Stdin = bytes.NewBuffer(config)
28 | proc.Stderr = os.Stderr
29 | proc.Stdout = os.Stdout
30 |
31 | return proc
32 | }
33 |
--------------------------------------------------------------------------------
/transport/internet/connection.go:
--------------------------------------------------------------------------------
1 | package internet
2 |
3 | import (
4 | "net"
5 |
6 | "github.com/Shadowsocks-NET/v2ray-go/v4/features/stats"
7 | )
8 |
9 | type Connection interface {
10 | net.Conn
11 | }
12 |
13 | type StatCouterConnection struct {
14 | Connection
15 | ReadCounter stats.Counter
16 | WriteCounter stats.Counter
17 | }
18 |
19 | func (c *StatCouterConnection) Read(b []byte) (int, error) {
20 | nBytes, err := c.Connection.Read(b)
21 | if c.ReadCounter != nil {
22 | c.ReadCounter.Add(int64(nBytes))
23 | }
24 |
25 | return nBytes, err
26 | }
27 |
28 | func (c *StatCouterConnection) Write(b []byte) (int, error) {
29 | nBytes, err := c.Connection.Write(b)
30 | if c.WriteCounter != nil {
31 | c.WriteCounter.Add(int64(nBytes))
32 | }
33 | return nBytes, err
34 | }
35 |
--------------------------------------------------------------------------------
/transport/pipe/reader.go:
--------------------------------------------------------------------------------
1 | package pipe
2 |
3 | import (
4 | "time"
5 |
6 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/buf"
7 | )
8 |
9 | // Reader is a buf.Reader that reads content from a pipe.
10 | type Reader struct {
11 | pipe *pipe
12 | }
13 |
14 | // ReadMultiBuffer implements buf.Reader.
15 | func (r *Reader) ReadMultiBuffer() (buf.MultiBuffer, error) {
16 | return r.pipe.ReadMultiBuffer()
17 | }
18 |
19 | // ReadMultiBufferTimeout reads content from a pipe within the given duration, or returns buf.ErrTimeout otherwise.
20 | func (r *Reader) ReadMultiBufferTimeout(d time.Duration) (buf.MultiBuffer, error) {
21 | return r.pipe.ReadMultiBufferTimeout(d)
22 | }
23 |
24 | // Interrupt implements common.Interruptible.
25 | func (r *Reader) Interrupt() {
26 | r.pipe.Interrupt()
27 | }
28 |
--------------------------------------------------------------------------------
/infra/conf/dns_proxy.go:
--------------------------------------------------------------------------------
1 | package conf
2 |
3 | import (
4 | "github.com/golang/protobuf/proto"
5 |
6 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/net"
7 | "github.com/Shadowsocks-NET/v2ray-go/v4/infra/conf/cfgcommon"
8 | "github.com/Shadowsocks-NET/v2ray-go/v4/proxy/dns"
9 | )
10 |
11 | type DNSOutboundConfig struct {
12 | Network cfgcommon.Network `json:"network"`
13 | Address *cfgcommon.Address `json:"address"`
14 | Port uint16 `json:"port"`
15 | }
16 |
17 | func (c *DNSOutboundConfig) Build() (proto.Message, error) {
18 | config := &dns.Config{
19 | Server: &net.Endpoint{
20 | Network: c.Network.Build(),
21 | Port: uint32(c.Port),
22 | },
23 | }
24 | if c.Address != nil {
25 | config.Server.Address = c.Address.Build()
26 | }
27 | return config, nil
28 | }
29 |
--------------------------------------------------------------------------------
/release/debian/rules:
--------------------------------------------------------------------------------
1 | #!/usr/bin/make -f
2 |
3 | include /usr/share/dpkg/default.mk
4 |
5 | BUILDDIR=_build
6 |
7 | %:
8 | dh $@ --builddirectory=$(BUILDDIR) --buildsystem=golang --with=golang
9 |
10 | execute_after_dh_auto_configure:
11 | go mod vendor
12 | cp -r vendor/* _build/src
13 |
14 | override_dh_auto_clean:
15 | dh_auto_clean
16 | rm -rf vendor
17 |
18 | override_dh_auto_build:
19 | DH_GOPKG="github.com/Shadowsocks-NET/v2ray-go/v4/main" dh_auto_build -- -ldflags "-s -w"
20 | cd $(BUILDDIR); mv bin/main bin/v2ray
21 | DH_GOPKG="github.com/Shadowsocks-NET/v2ray-go/v4/infra/control/main" dh_auto_build -- -ldflags "-s -w" -tags confonly
22 | cd $(BUILDDIR); mv bin/main bin/v2ctl
23 |
24 | override_dh_auto_install:
25 | dh_auto_install -- --no-source
26 |
27 | override_dh_auto_test:
28 |
--------------------------------------------------------------------------------
/transport/internet/headers/tls/dtls_test.go:
--------------------------------------------------------------------------------
1 | package tls_test
2 |
3 | import (
4 | "context"
5 | "testing"
6 |
7 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
8 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/buf"
9 | . "github.com/Shadowsocks-NET/v2ray-go/v4/transport/internet/headers/tls"
10 | )
11 |
12 | func TestDTLSWrite(t *testing.T) {
13 | content := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g'}
14 | dtlsRaw, err := New(context.Background(), &PacketConfig{})
15 | common.Must(err)
16 |
17 | dtls := dtlsRaw.(*DTLS)
18 |
19 | payload := buf.New()
20 | dtls.Serialize(payload.Extend(dtls.Size()))
21 | payload.Write(content)
22 |
23 | if payload.Len() != int32(len(content))+dtls.Size() {
24 | t.Error("payload len: ", payload.Len(), " want ", int32(len(content))+dtls.Size())
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/transport/internet/quic/quic.go:
--------------------------------------------------------------------------------
1 | //go:build !confonly
2 | // +build !confonly
3 |
4 | package quic
5 |
6 | import (
7 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
8 | "github.com/Shadowsocks-NET/v2ray-go/v4/transport/internet"
9 | )
10 |
11 | //go:generate go run github.com/Shadowsocks-NET/v2ray-go/v4/common/errors/errorgen
12 |
13 | // Here is some modification needs to be done before update quic vendor.
14 | // * use bytespool in buffer_pool.go
15 | // * set MaxReceivePacketSize to 1452 - 32 (16 bytes auth, 16 bytes head)
16 | //
17 | //
18 |
19 | const (
20 | protocolName = "quic"
21 | internalDomain = "quic.internal.v2fly.org"
22 | )
23 |
24 | func init() {
25 | common.Must(internet.RegisterProtocolConfigCreator(protocolName, func() interface{} {
26 | return new(Config)
27 | }))
28 | }
29 |
--------------------------------------------------------------------------------
/features/feature.go:
--------------------------------------------------------------------------------
1 | package features
2 |
3 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common"
4 |
5 | //go:generate go run github.com/Shadowsocks-NET/v2ray-go/v4/common/errors/errorgen
6 |
7 | // Feature is the interface for V2Ray features. All features must implement this interface.
8 | // All existing features have an implementation in app directory. These features can be replaced by third-party ones.
9 | type Feature interface {
10 | common.HasType
11 | common.Runnable
12 | }
13 |
14 | // PrintDeprecatedFeatureWarning prints a warning for deprecated feature.
15 | func PrintDeprecatedFeatureWarning(feature string) {
16 | newError("You are using a deprecated feature: " + feature + ". Please update your config file with latest configuration format, or update your client software.").WriteToLog()
17 | }
18 |
--------------------------------------------------------------------------------
/infra/conf/policy_test.go:
--------------------------------------------------------------------------------
1 | package conf_test
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
7 | . "github.com/Shadowsocks-NET/v2ray-go/v4/infra/conf"
8 | )
9 |
10 | func TestBufferSize(t *testing.T) {
11 | cases := []struct {
12 | Input int32
13 | Output int32
14 | }{
15 | {
16 | Input: 0,
17 | Output: 0,
18 | },
19 | {
20 | Input: -1,
21 | Output: -1,
22 | },
23 | {
24 | Input: 1,
25 | Output: 1024,
26 | },
27 | }
28 |
29 | for _, c := range cases {
30 | bs := c.Input
31 | pConf := Policy{
32 | BufferSize: &bs,
33 | }
34 | p, err := pConf.Build()
35 | common.Must(err)
36 | if p.Buffer.Connection != c.Output {
37 | t.Error("expected buffer size ", c.Output, " but got ", p.Buffer.Connection)
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/infra/conf/blackhole_test.go:
--------------------------------------------------------------------------------
1 | package conf_test
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/serial"
7 | . "github.com/Shadowsocks-NET/v2ray-go/v4/infra/conf"
8 | "github.com/Shadowsocks-NET/v2ray-go/v4/proxy/blackhole"
9 | )
10 |
11 | func TestHTTPResponseJSON(t *testing.T) {
12 | creator := func() Buildable {
13 | return new(BlackholeConfig)
14 | }
15 |
16 | runMultiTestCase(t, []TestCase{
17 | {
18 | Input: `{
19 | "response": {
20 | "type": "http"
21 | }
22 | }`,
23 | Parser: loadJSON(creator),
24 | Output: &blackhole.Config{
25 | Response: serial.ToTypedMessage(&blackhole.HTTPResponse{}),
26 | },
27 | },
28 | {
29 | Input: `{}`,
30 | Parser: loadJSON(creator),
31 | Output: &blackhole.Config{},
32 | },
33 | })
34 | }
35 |
--------------------------------------------------------------------------------
/infra/conf/dns_proxy_test.go:
--------------------------------------------------------------------------------
1 | package conf_test
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/net"
7 | . "github.com/Shadowsocks-NET/v2ray-go/v4/infra/conf"
8 | "github.com/Shadowsocks-NET/v2ray-go/v4/proxy/dns"
9 | )
10 |
11 | func TestDnsProxyConfig(t *testing.T) {
12 | creator := func() Buildable {
13 | return new(DNSOutboundConfig)
14 | }
15 |
16 | runMultiTestCase(t, []TestCase{
17 | {
18 | Input: `{
19 | "address": "8.8.8.8",
20 | "port": 53,
21 | "network": "tcp"
22 | }`,
23 | Parser: loadJSON(creator),
24 | Output: &dns.Config{
25 | Server: &net.Endpoint{
26 | Network: net.Network_TCP,
27 | Address: net.NewIPOrDomain(net.IPAddress([]byte{8, 8, 8, 8})),
28 | Port: 53,
29 | },
30 | },
31 | },
32 | })
33 | }
34 |
--------------------------------------------------------------------------------
/proxy/vmess/aead/consts.go:
--------------------------------------------------------------------------------
1 | package aead
2 |
3 | const (
4 | KDFSaltConstAuthIDEncryptionKey = "AES Auth ID Encryption"
5 | KDFSaltConstAEADRespHeaderLenKey = "AEAD Resp Header Len Key"
6 | KDFSaltConstAEADRespHeaderLenIV = "AEAD Resp Header Len IV"
7 | KDFSaltConstAEADRespHeaderPayloadKey = "AEAD Resp Header Key"
8 | KDFSaltConstAEADRespHeaderPayloadIV = "AEAD Resp Header IV"
9 | KDFSaltConstVMessAEADKDF = "VMess AEAD KDF"
10 | KDFSaltConstVMessHeaderPayloadAEADKey = "VMess Header AEAD Key"
11 | KDFSaltConstVMessHeaderPayloadAEADIV = "VMess Header AEAD Nonce"
12 | KDFSaltConstVMessHeaderPayloadLengthAEADKey = "VMess Header AEAD Key_Length"
13 | KDFSaltConstVMessHeaderPayloadLengthAEADIV = "VMess Header AEAD Nonce_Length"
14 | )
15 |
--------------------------------------------------------------------------------
/app/commander/config.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.app.commander;
4 | option csharp_namespace = "V2Ray.Core.App.Commander";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/app/commander";
6 | option java_package = "com.v2ray.core.app.commander";
7 | option java_multiple_files = true;
8 |
9 | import "common/serial/typed_message.proto";
10 |
11 | // Config is the settings for Commander.
12 | message Config {
13 | // Tag of the outbound handler that handles grpc connections.
14 | string tag = 1;
15 | // Services that supported by this server. All services must implement Service
16 | // interface.
17 | repeated v2ray.core.common.serial.TypedMessage service = 2;
18 | }
19 |
20 | // ReflectionConfig is the placeholder config for ReflectionService.
21 | message ReflectionConfig {}
22 |
--------------------------------------------------------------------------------
/infra/conf/lint.go:
--------------------------------------------------------------------------------
1 | package conf
2 |
3 | type ConfigureFilePostProcessingStage interface {
4 | Process(conf *Config) error
5 | }
6 |
7 | var configureFilePostProcessingStages map[string]ConfigureFilePostProcessingStage
8 |
9 | func RegisterConfigureFilePostProcessingStage(name string, stage ConfigureFilePostProcessingStage) {
10 | if configureFilePostProcessingStages == nil {
11 | configureFilePostProcessingStages = make(map[string]ConfigureFilePostProcessingStage)
12 | }
13 | configureFilePostProcessingStages[name] = stage
14 | }
15 |
16 | func PostProcessConfigureFile(conf *Config) error {
17 | for k, v := range configureFilePostProcessingStages {
18 | if err := v.Process(conf); err != nil {
19 | return newError("Rejected by Postprocessing Stage ", k).AtError().Base(err)
20 | }
21 | }
22 | return nil
23 | }
24 |
--------------------------------------------------------------------------------
/transport/internet/tcp/sockopt_freebsd.go:
--------------------------------------------------------------------------------
1 | //go:build freebsd && !confonly
2 | // +build freebsd,!confonly
3 |
4 | package tcp
5 |
6 | import (
7 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/net"
8 | "github.com/Shadowsocks-NET/v2ray-go/v4/transport/internet"
9 | )
10 |
11 | // GetOriginalDestination from tcp conn
12 | func GetOriginalDestination(conn internet.Connection) (net.Destination, error) {
13 | la := conn.LocalAddr()
14 | ra := conn.RemoteAddr()
15 | ip, port, err := internet.OriginalDst(la, ra)
16 | if err != nil {
17 | return net.Destination{}, newError("failed to get destination").Base(err)
18 | }
19 | dest := net.TCPDestination(net.IPAddress(ip), net.Port(port))
20 | if !dest.IsValid() {
21 | return net.Destination{}, newError("failed to parse destination.")
22 | }
23 | return dest, nil
24 | }
25 |
--------------------------------------------------------------------------------
/proxy/vmess/aead/kdf.go:
--------------------------------------------------------------------------------
1 | package aead
2 |
3 | import (
4 | "crypto/hmac"
5 | "crypto/sha256"
6 | "hash"
7 | )
8 |
9 | func KDF(key []byte, path ...string) []byte {
10 | hmacCreator := &hMacCreator{value: []byte(KDFSaltConstVMessAEADKDF)}
11 | for _, v := range path {
12 | hmacCreator = &hMacCreator{value: []byte(v), parent: hmacCreator}
13 | }
14 | hmacf := hmacCreator.Create()
15 | hmacf.Write(key)
16 | return hmacf.Sum(nil)
17 | }
18 |
19 | type hMacCreator struct {
20 | parent *hMacCreator
21 | value []byte
22 | }
23 |
24 | func (h *hMacCreator) Create() hash.Hash {
25 | if h.parent == nil {
26 | return hmac.New(sha256.New, h.value)
27 | }
28 | return hmac.New(h.parent.Create, h.value)
29 | }
30 |
31 | func KDF16(key []byte, path ...string) []byte {
32 | r := KDF(key, path...)
33 | return r[:16]
34 | }
35 |
--------------------------------------------------------------------------------
/transport/internet/headers/srtp/srtp_test.go:
--------------------------------------------------------------------------------
1 | package srtp_test
2 |
3 | import (
4 | "context"
5 | "testing"
6 |
7 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
8 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/buf"
9 | . "github.com/Shadowsocks-NET/v2ray-go/v4/transport/internet/headers/srtp"
10 | )
11 |
12 | func TestSRTPWrite(t *testing.T) {
13 | content := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g'}
14 | srtpRaw, err := New(context.Background(), &Config{})
15 | common.Must(err)
16 |
17 | srtp := srtpRaw.(*SRTP)
18 |
19 | payload := buf.New()
20 | srtp.Serialize(payload.Extend(srtp.Size()))
21 | payload.Write(content)
22 |
23 | expectedLen := int32(len(content)) + srtp.Size()
24 | if payload.Len() != expectedLen {
25 | t.Error("expected ", expectedLen, " of bytes, but got ", payload.Len())
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/transport/internet/udp/dialer.go:
--------------------------------------------------------------------------------
1 | package udp
2 |
3 | import (
4 | "context"
5 |
6 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
7 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/net"
8 | "github.com/Shadowsocks-NET/v2ray-go/v4/transport/internet"
9 | )
10 |
11 | func init() {
12 | common.Must(internet.RegisterTransportDialer(protocolName,
13 | func(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (internet.Connection, error) {
14 | var sockopt *internet.SocketConfig
15 | if streamSettings != nil {
16 | sockopt = streamSettings.SocketSettings
17 | }
18 | conn, err := internet.DialSystem(ctx, dest, sockopt)
19 | if err != nil {
20 | return nil, err
21 | }
22 | // TODO: handle dialer options
23 | return internet.Connection(conn), nil
24 | }))
25 | }
26 |
--------------------------------------------------------------------------------
/transport/internet/system_dns_android.go:
--------------------------------------------------------------------------------
1 | //go:build android
2 | // +build android
3 |
4 | package internet
5 |
6 | import (
7 | "context"
8 | "net"
9 | )
10 |
11 | const SystemDNS = "8.8.8.8:53"
12 |
13 | /* DNSResolverFunc
14 | This is a temporary API and is subject to removal at any time.
15 | */
16 | type DNSResolverFunc func() *net.Resolver
17 |
18 | /* NewDNSResolver
19 | This is a temporary API and is subject to removal at any time.
20 | */
21 | var NewDNSResolver DNSResolverFunc = func() *net.Resolver {
22 | return &net.Resolver{
23 | PreferGo: true,
24 | Dial: func(ctx context.Context, network, _ string) (net.Conn, error) {
25 | var dialer net.Dialer
26 | return dialer.DialContext(ctx, network, SystemDNS)
27 | },
28 | }
29 | }
30 |
31 | func init() {
32 | net.DefaultResolver = NewDNSResolver()
33 | }
34 |
--------------------------------------------------------------------------------
/transport/internet/dialer_test.go:
--------------------------------------------------------------------------------
1 | package internet_test
2 |
3 | import (
4 | "context"
5 | "testing"
6 |
7 | "github.com/google/go-cmp/cmp"
8 |
9 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
10 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/net"
11 | "github.com/Shadowsocks-NET/v2ray-go/v4/testing/servers/tcp"
12 | . "github.com/Shadowsocks-NET/v2ray-go/v4/transport/internet"
13 | )
14 |
15 | func TestDialWithLocalAddr(t *testing.T) {
16 | server := &tcp.Server{}
17 | dest, err := server.Start()
18 | common.Must(err)
19 | defer server.Close()
20 |
21 | conn, err := DialSystem(context.Background(), net.TCPDestination(net.LocalHostIP, dest.Port), nil)
22 | common.Must(err)
23 | if r := cmp.Diff(conn.RemoteAddr().String(), "127.0.0.1:"+dest.Port.String()); r != "" {
24 | t.Error(r)
25 | }
26 | conn.Close()
27 | }
28 |
--------------------------------------------------------------------------------
/transport/internet/websocket/config.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.transport.internet.websocket;
4 | option csharp_namespace = "V2Ray.Core.Transport.Internet.Websocket";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/transport/internet/websocket";
6 | option java_package = "com.v2ray.core.transport.internet.websocket";
7 | option java_multiple_files = true;
8 |
9 | message Header {
10 | string key = 1;
11 | string value = 2;
12 | }
13 |
14 | message Config {
15 | reserved 1;
16 |
17 | // URL path to the WebSocket service. Empty value means root(/).
18 | string path = 2;
19 |
20 | repeated Header header = 3;
21 |
22 | bool accept_proxy_protocol = 4;
23 |
24 | int32 max_early_data = 5;
25 |
26 | bool use_browser_forwarding = 6;
27 |
28 | string early_data_header_name = 7;
29 | }
30 |
--------------------------------------------------------------------------------
/infra/conf/cfgcommon/duration/duration_test.go:
--------------------------------------------------------------------------------
1 | package duration_test
2 |
3 | import (
4 | "encoding/json"
5 | "testing"
6 | "time"
7 |
8 | "github.com/Shadowsocks-NET/v2ray-go/v4/infra/conf/cfgcommon/duration"
9 | )
10 |
11 | type testWithDuration struct {
12 | Duration duration.Duration
13 | }
14 |
15 | func TestDurationJSON(t *testing.T) {
16 | expected := &testWithDuration{
17 | Duration: duration.Duration(time.Hour),
18 | }
19 | data, err := json.Marshal(expected)
20 | if err != nil {
21 | t.Error(err)
22 | return
23 | }
24 | actual := &testWithDuration{}
25 | err = json.Unmarshal(data, &actual)
26 | if err != nil {
27 | t.Error(err)
28 | return
29 | }
30 | if actual.Duration != expected.Duration {
31 | t.Errorf("expected: %s, actual: %s", time.Duration(expected.Duration), time.Duration(actual.Duration))
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/proxy/http/config.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.proxy.http;
4 | option csharp_namespace = "V2Ray.Core.Proxy.Http";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/proxy/http";
6 | option java_package = "com.v2ray.core.proxy.http";
7 | option java_multiple_files = true;
8 |
9 | import "common/protocol/server_spec.proto";
10 |
11 | message Account {
12 | string username = 1;
13 | string password = 2;
14 | }
15 |
16 | // Config for HTTP proxy server.
17 | message ServerConfig {
18 | map accounts = 2;
19 | bool allow_transparent = 3;
20 | uint32 user_level = 4;
21 | }
22 |
23 | // ClientConfig is the protobuf config for HTTP proxy client.
24 | message ClientConfig {
25 | // Sever is a list of HTTP server addresses.
26 | repeated v2ray.core.common.protocol.ServerEndpoint server = 1;
27 | }
28 |
--------------------------------------------------------------------------------
/transport/internet/kcp/io_test.go:
--------------------------------------------------------------------------------
1 | package kcp_test
2 |
3 | import (
4 | "testing"
5 |
6 | . "github.com/Shadowsocks-NET/v2ray-go/v4/transport/internet/kcp"
7 | )
8 |
9 | func TestKCPPacketReader(t *testing.T) {
10 | reader := KCPPacketReader{
11 | Security: &SimpleAuthenticator{},
12 | }
13 |
14 | testCases := []struct {
15 | Input []byte
16 | Output []Segment
17 | }{
18 | {
19 | Input: []byte{},
20 | Output: nil,
21 | },
22 | {
23 | Input: []byte{1},
24 | Output: nil,
25 | },
26 | }
27 |
28 | for _, testCase := range testCases {
29 | seg := reader.Read(testCase.Input)
30 | if testCase.Output == nil && seg != nil {
31 | t.Errorf("Expect nothing returned, but actually %v", seg)
32 | } else if testCase.Output != nil && seg == nil {
33 | t.Errorf("Expect some output, but got nil")
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/app/stats/counter_test.go:
--------------------------------------------------------------------------------
1 | package stats_test
2 |
3 | import (
4 | "context"
5 | "testing"
6 |
7 | . "github.com/Shadowsocks-NET/v2ray-go/v4/app/stats"
8 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
9 | "github.com/Shadowsocks-NET/v2ray-go/v4/features/stats"
10 | )
11 |
12 | func TestStatsCounter(t *testing.T) {
13 | raw, err := common.CreateObject(context.Background(), &Config{})
14 | common.Must(err)
15 |
16 | m := raw.(stats.Manager)
17 | c, err := m.RegisterCounter("test.counter")
18 | common.Must(err)
19 |
20 | if v := c.Add(1); v != 1 {
21 | t.Fatal("unpexcted Add(1) return: ", v, ", wanted ", 1)
22 | }
23 |
24 | if v := c.Set(0); v != 1 {
25 | t.Fatal("unexpected Set(0) return: ", v, ", wanted ", 1)
26 | }
27 |
28 | if v := c.Value(); v != 0 {
29 | t.Fatal("unexpected Value() return: ", v, ", wanted ", 0)
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/release/install-release.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # This file is accessible as https://install.direct/go.sh
4 | # Original source is located at github.com/v2fly/v2ray-core/release/install-release.sh
5 |
6 | # If not specify, default meaning of return value:
7 | # 0: Success
8 | # 1: System error
9 | # 2: Application error
10 | # 3: Network error
11 |
12 | #######color code########
13 | RED="31m" # Error message
14 | YELLOW="33m" # Warning message
15 | colorEcho(){
16 | echo -e "\033[${1}${@:2}\033[0m" 1>& 2
17 | }
18 |
19 | colorEcho ${RED} "ERROR: This script has been DISCARDED, please switch to fhs-install-v2ray project."
20 | colorEcho ${YELLOW} "HOW TO USE: https://github.com/v2fly/fhs-install-v2ray"
21 | colorEcho ${YELLOW} "TO MIGRATE: https://github.com/v2fly/fhs-install-v2ray/wiki/Migrate-from-the-old-script-to-this"
22 | exit 255
23 |
--------------------------------------------------------------------------------
/proxy/dokodemo/config.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.proxy.dokodemo;
4 | option csharp_namespace = "V2Ray.Core.Proxy.Dokodemo";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/proxy/dokodemo";
6 | option java_package = "com.v2ray.core.proxy.dokodemo";
7 | option java_multiple_files = true;
8 |
9 | import "common/net/address.proto";
10 | import "common/net/network.proto";
11 |
12 | message Config {
13 | v2ray.core.common.net.IPOrDomain address = 1;
14 | uint32 port = 2;
15 |
16 | // List of networks that the Dokodemo accepts.
17 | // Deprecated. Use networks.
18 | v2ray.core.common.net.NetworkList network_list = 3 [deprecated = true];
19 | // List of networks that the Dokodemo accepts.
20 | repeated v2ray.core.common.net.Network networks = 7;
21 |
22 | bool follow_redirect = 5;
23 | uint32 user_level = 6;
24 | }
25 |
--------------------------------------------------------------------------------
/transport/internet/websocket/config.go:
--------------------------------------------------------------------------------
1 | //go:build !confonly
2 | // +build !confonly
3 |
4 | package websocket
5 |
6 | import (
7 | "net/http"
8 |
9 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
10 | "github.com/Shadowsocks-NET/v2ray-go/v4/transport/internet"
11 | )
12 |
13 | const protocolName = "websocket"
14 |
15 | func (c *Config) GetNormalizedPath() string {
16 | path := c.Path
17 | if path == "" {
18 | return "/"
19 | }
20 | if path[0] != '/' {
21 | return "/" + path
22 | }
23 | return path
24 | }
25 |
26 | func (c *Config) GetRequestHeader() http.Header {
27 | header := http.Header{}
28 | for _, h := range c.Header {
29 | header.Add(h.Key, h.Value)
30 | }
31 | return header
32 | }
33 |
34 | func init() {
35 | common.Must(internet.RegisterProtocolConfigCreator(protocolName, func() interface{} {
36 | return new(Config)
37 | }))
38 | }
39 |
--------------------------------------------------------------------------------
/infra/conf/http_test.go:
--------------------------------------------------------------------------------
1 | package conf_test
2 |
3 | import (
4 | "testing"
5 |
6 | . "github.com/Shadowsocks-NET/v2ray-go/v4/infra/conf"
7 | "github.com/Shadowsocks-NET/v2ray-go/v4/proxy/http"
8 | )
9 |
10 | func TestHTTPServerConfig(t *testing.T) {
11 | creator := func() Buildable {
12 | return new(HTTPServerConfig)
13 | }
14 |
15 | runMultiTestCase(t, []TestCase{
16 | {
17 | Input: `{
18 | "timeout": 10,
19 | "accounts": [
20 | {
21 | "user": "my-username",
22 | "pass": "my-password"
23 | }
24 | ],
25 | "allowTransparent": true,
26 | "userLevel": 1
27 | }`,
28 | Parser: loadJSON(creator),
29 | Output: &http.ServerConfig{
30 | Accounts: map[string]string{
31 | "my-username": "my-password",
32 | },
33 | AllowTransparent: true,
34 | UserLevel: 1,
35 | },
36 | },
37 | })
38 | }
39 |
--------------------------------------------------------------------------------
/proxy/trojan/config.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.proxy.trojan;
4 | option csharp_namespace = "V2Ray.Core.Proxy.Trojan";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/proxy/trojan";
6 | option java_package = "com.v2ray.core.proxy.trojan";
7 | option java_multiple_files = true;
8 |
9 | import "common/protocol/user.proto";
10 | import "common/protocol/server_spec.proto";
11 |
12 | message Account {
13 | string password = 1;
14 | }
15 |
16 | message Fallback {
17 | string alpn = 1;
18 | string path = 2;
19 | string type = 3;
20 | string dest = 4;
21 | uint64 xver = 5;
22 | }
23 |
24 | message ClientConfig {
25 | repeated v2ray.core.common.protocol.ServerEndpoint server = 1;
26 | }
27 |
28 | message ServerConfig {
29 | repeated v2ray.core.common.protocol.User users = 1;
30 | repeated Fallback fallbacks = 3;
31 | }
32 |
--------------------------------------------------------------------------------
/common/serial/serial.go:
--------------------------------------------------------------------------------
1 | package serial
2 |
3 | import (
4 | "encoding/binary"
5 | "io"
6 | )
7 |
8 | // ReadUint16 reads first two bytes from the reader, and then coverts them to an uint16 value.
9 | func ReadUint16(reader io.Reader) (uint16, error) {
10 | var b [2]byte
11 | if _, err := io.ReadFull(reader, b[:]); err != nil {
12 | return 0, err
13 | }
14 | return binary.BigEndian.Uint16(b[:]), nil
15 | }
16 |
17 | // WriteUint16 writes an uint16 value into writer.
18 | func WriteUint16(writer io.Writer, value uint16) (int, error) {
19 | var b [2]byte
20 | binary.BigEndian.PutUint16(b[:], value)
21 | return writer.Write(b[:])
22 | }
23 |
24 | // WriteUint64 writes an uint64 value into writer.
25 | func WriteUint64(writer io.Writer, value uint64) (int, error) {
26 | var b [8]byte
27 | binary.BigEndian.PutUint64(b[:], value)
28 | return writer.Write(b[:])
29 | }
30 |
--------------------------------------------------------------------------------
/common/bitmask/byte_test.go:
--------------------------------------------------------------------------------
1 | package bitmask_test
2 |
3 | import (
4 | "testing"
5 |
6 | . "github.com/Shadowsocks-NET/v2ray-go/v4/common/bitmask"
7 | )
8 |
9 | func TestBitmaskByte(t *testing.T) {
10 | b := Byte(0)
11 | b.Set(Byte(1))
12 | if !b.Has(1) {
13 | t.Fatal("expected ", b, " to contain 1, but actually not")
14 | }
15 |
16 | b.Set(Byte(2))
17 | if !b.Has(2) {
18 | t.Fatal("expected ", b, " to contain 2, but actually not")
19 | }
20 | if !b.Has(1) {
21 | t.Fatal("expected ", b, " to contain 1, but actually not")
22 | }
23 |
24 | b.Clear(Byte(1))
25 | if !b.Has(2) {
26 | t.Fatal("expected ", b, " to contain 2, but actually not")
27 | }
28 | if b.Has(1) {
29 | t.Fatal("expected ", b, " to not contain 1, but actually did")
30 | }
31 |
32 | b.Toggle(Byte(2))
33 | if b.Has(2) {
34 | t.Fatal("expected ", b, " to not contain 2, but actually did")
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/.github/linters/.golangci.yml:
--------------------------------------------------------------------------------
1 | run:
2 | timeout: 5m
3 | skip-files:
4 | - generated.*
5 |
6 | issues:
7 | new: true
8 | exclude-rules:
9 | - linters:
10 | - staticcheck
11 | text: "SA1019:"
12 |
13 | linters:
14 | enable:
15 | - asciicheck
16 | - bodyclose
17 | - depguard
18 | - gocritic
19 | - gofmt
20 | - gofumpt
21 | - goimports
22 | - golint
23 | - goprintffuncname
24 | - gosimple
25 | - govet
26 | - ineffassign
27 | - misspell
28 | - nakedret
29 | - rowserrcheck
30 | - staticcheck
31 | - structcheck
32 | - stylecheck
33 | - typecheck
34 | - unconvert
35 | - unparam
36 | - varcheck
37 | - whitespace
38 | disable:
39 | - deadcode
40 | - errcheck
41 | - unused
42 |
43 | linters-settings:
44 | goimports:
45 | local-prefixes: github.com/Shadowsocks-NET/v2ray-go
46 |
--------------------------------------------------------------------------------
/common/errors/errorgen/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "os"
6 | "path/filepath"
7 | )
8 |
9 | func main() {
10 | pwd, err := os.Getwd()
11 | if err != nil {
12 | fmt.Println("can not get current working directory")
13 | os.Exit(1)
14 | }
15 | pkg := filepath.Base(pwd)
16 | if pkg == "v2ray-core" {
17 | pkg = "core"
18 | }
19 |
20 | file, err := os.OpenFile("errors.generated.go", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0o644)
21 | if err != nil {
22 | fmt.Printf("Failed to generate errors.generated.go: %v", err)
23 | os.Exit(1)
24 | }
25 | defer file.Close()
26 |
27 | fmt.Fprintf(file, `package %s
28 |
29 | import "github.com/Shadowsocks-NET/v2ray-go/v4/common/errors"
30 |
31 | type errPathObjHolder struct{}
32 |
33 | func newError(values ...interface{}) *errors.Error {
34 | return errors.New(values...).WithPathObj(errPathObjHolder{})
35 | }
36 | `, pkg)
37 | }
38 |
--------------------------------------------------------------------------------
/transport/internet/headers/srtp/srtp.go:
--------------------------------------------------------------------------------
1 | package srtp
2 |
3 | import (
4 | "context"
5 | "encoding/binary"
6 |
7 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
8 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/dice"
9 | )
10 |
11 | type SRTP struct {
12 | header uint16
13 | number uint16
14 | }
15 |
16 | func (*SRTP) Size() int32 {
17 | return 4
18 | }
19 |
20 | // Serialize implements PacketHeader.
21 | func (s *SRTP) Serialize(b []byte) {
22 | s.number++
23 | binary.BigEndian.PutUint16(b, s.header)
24 | binary.BigEndian.PutUint16(b[2:], s.number)
25 | }
26 |
27 | // New returns a new SRTP instance based on the given config.
28 | func New(ctx context.Context, config interface{}) (interface{}, error) {
29 | return &SRTP{
30 | header: 0xB5E8,
31 | number: dice.RollUint16(),
32 | }, nil
33 | }
34 |
35 | func init() {
36 | common.Must(common.RegisterConfig((*Config)(nil), New))
37 | }
38 |
--------------------------------------------------------------------------------
/common/buf/readv_windows.go:
--------------------------------------------------------------------------------
1 | package buf
2 |
3 | import (
4 | "syscall"
5 | )
6 |
7 | type windowsReader struct {
8 | bufs []syscall.WSABuf
9 | }
10 |
11 | func (r *windowsReader) Init(bs []*Buffer) {
12 | if r.bufs == nil {
13 | r.bufs = make([]syscall.WSABuf, 0, len(bs))
14 | }
15 | for _, b := range bs {
16 | r.bufs = append(r.bufs, syscall.WSABuf{Len: uint32(Size), Buf: &b.v[0]})
17 | }
18 | }
19 |
20 | func (r *windowsReader) Clear() {
21 | for idx := range r.bufs {
22 | r.bufs[idx].Buf = nil
23 | }
24 | r.bufs = r.bufs[:0]
25 | }
26 |
27 | func (r *windowsReader) Read(fd uintptr) int32 {
28 | var nBytes uint32
29 | var flags uint32
30 | err := syscall.WSARecv(syscall.Handle(fd), &r.bufs[0], uint32(len(r.bufs)), &nBytes, &flags, nil, nil)
31 | if err != nil {
32 | return -1
33 | }
34 | return int32(nBytes)
35 | }
36 |
37 | func newMultiReader() multiReader {
38 | return new(windowsReader)
39 | }
40 |
--------------------------------------------------------------------------------
/infra/conf/dokodemo.go:
--------------------------------------------------------------------------------
1 | package conf
2 |
3 | import (
4 | "github.com/golang/protobuf/proto"
5 |
6 | "github.com/Shadowsocks-NET/v2ray-go/v4/infra/conf/cfgcommon"
7 | "github.com/Shadowsocks-NET/v2ray-go/v4/proxy/dokodemo"
8 | )
9 |
10 | type DokodemoConfig struct {
11 | Host *cfgcommon.Address `json:"address"`
12 | PortValue uint16 `json:"port"`
13 | NetworkList *cfgcommon.NetworkList `json:"network"`
14 | Redirect bool `json:"followRedirect"`
15 | UserLevel uint32 `json:"userLevel"`
16 | }
17 |
18 | func (v *DokodemoConfig) Build() (proto.Message, error) {
19 | config := new(dokodemo.Config)
20 | if v.Host != nil {
21 | config.Address = v.Host.Build()
22 | }
23 | config.Port = uint32(v.PortValue)
24 | config.Networks = v.NetworkList.Build()
25 | config.FollowRedirect = v.Redirect
26 | config.UserLevel = v.UserLevel
27 | return config, nil
28 | }
29 |
--------------------------------------------------------------------------------
/features/routing/dispatcher.go:
--------------------------------------------------------------------------------
1 | package routing
2 |
3 | import (
4 | "context"
5 |
6 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/net"
7 | "github.com/Shadowsocks-NET/v2ray-go/v4/features"
8 | "github.com/Shadowsocks-NET/v2ray-go/v4/transport"
9 | )
10 |
11 | // Dispatcher is a feature that dispatches inbound requests to outbound handlers based on rules.
12 | // Dispatcher is required to be registered in a V2Ray instance to make V2Ray function properly.
13 | //
14 | // v2ray:api:stable
15 | type Dispatcher interface {
16 | features.Feature
17 |
18 | // Dispatch returns a Ray for transporting data for the given request.
19 | Dispatch(ctx context.Context, dest net.Destination) (*transport.Link, error)
20 | }
21 |
22 | // DispatcherType returns the type of Dispatcher interface. Can be used to implement common.HasType.
23 | //
24 | // v2ray:api:stable
25 | func DispatcherType() interface{} {
26 | return (*Dispatcher)(nil)
27 | }
28 |
--------------------------------------------------------------------------------
/transport/internet/headers/utp/utp.go:
--------------------------------------------------------------------------------
1 | package utp
2 |
3 | import (
4 | "context"
5 | "encoding/binary"
6 |
7 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
8 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/dice"
9 | )
10 |
11 | type UTP struct {
12 | header byte
13 | extension byte
14 | connectionID uint16
15 | }
16 |
17 | func (*UTP) Size() int32 {
18 | return 4
19 | }
20 |
21 | // Serialize implements PacketHeader.
22 | func (u *UTP) Serialize(b []byte) {
23 | binary.BigEndian.PutUint16(b, u.connectionID)
24 | b[2] = u.header
25 | b[3] = u.extension
26 | }
27 |
28 | // New creates a new UTP header for the given config.
29 | func New(ctx context.Context, config interface{}) (interface{}, error) {
30 | return &UTP{
31 | header: 1,
32 | extension: 0,
33 | connectionID: dice.RollUint16(),
34 | }, nil
35 | }
36 |
37 | func init() {
38 | common.Must(common.RegisterConfig((*Config)(nil), New))
39 | }
40 |
--------------------------------------------------------------------------------
/.github/workflows/linter.yml:
--------------------------------------------------------------------------------
1 | name: Linter
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | - v*
8 | paths:
9 | - "**/*.go"
10 | - ".github/workflows/linter.yml"
11 | pull_request:
12 | types: [opened, synchronize, reopened]
13 | paths:
14 | - "**/*.go"
15 | - ".github/workflows/linter.yml"
16 |
17 | jobs:
18 | lint:
19 | if: github.repository == 'Shadowsocks-NET/v2ray-go'
20 | runs-on: ubuntu-latest
21 | container:
22 | image: archlinux/archlinux:base-devel
23 | steps:
24 | - uses: actions/checkout@v3
25 |
26 | - name: Install dependencies
27 | run: |
28 | pacman -Syu --needed --noconfirm go protobuf
29 |
30 | - name: golangci-lint
31 | uses: golangci/golangci-lint-action@v3
32 | with:
33 | version: latest
34 | args: --config=.github/linters/.golangci.yml
35 | only-new-issues: true
36 |
--------------------------------------------------------------------------------
/transport/internet/domainsocket/config.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.transport.internet.domainsocket;
4 | option csharp_namespace = "V2Ray.Core.Transport.Internet.DomainSocket";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/transport/internet/domainsocket";
6 | option java_package = "com.v2ray.core.transport.internet.domainsocket";
7 | option java_multiple_files = true;
8 |
9 | message Config {
10 | // Path of the domain socket. This overrides the IP/Port parameter from
11 | // upstream caller.
12 | string path = 1;
13 | // Abstract speicifies whether to use abstract namespace or not.
14 | // Traditionally Unix domain socket is file system based. Abstract domain
15 | // socket can be used without acquiring file lock.
16 | bool abstract = 2;
17 | // Some apps, eg. haproxy, use the full length of sockaddr_un.sun_path to
18 | // connect(2) or bind(2) when using abstract UDS.
19 | bool padding = 3;
20 | }
21 |
--------------------------------------------------------------------------------
/transport/internet/headers/http/resp.go:
--------------------------------------------------------------------------------
1 | package http
2 |
3 | var resp400 = &ResponseConfig{
4 | Version: &Version{
5 | Value: "1.1",
6 | },
7 | Status: &Status{
8 | Code: "400",
9 | Reason: "Bad Request",
10 | },
11 | Header: []*Header{
12 | {
13 | Name: "Connection",
14 | Value: []string{"close"},
15 | },
16 | {
17 | Name: "Cache-Control",
18 | Value: []string{"private"},
19 | },
20 | {
21 | Name: "Content-Length",
22 | Value: []string{"0"},
23 | },
24 | },
25 | }
26 |
27 | var resp404 = &ResponseConfig{
28 | Version: &Version{
29 | Value: "1.1",
30 | },
31 | Status: &Status{
32 | Code: "404",
33 | Reason: "Not Found",
34 | },
35 | Header: []*Header{
36 | {
37 | Name: "Connection",
38 | Value: []string{"close"},
39 | },
40 | {
41 | Name: "Cache-Control",
42 | Value: []string{"private"},
43 | },
44 | {
45 | Name: "Content-Length",
46 | Value: []string{"0"},
47 | },
48 | },
49 | }
50 |
--------------------------------------------------------------------------------
/transport/internet/tls/pin.go:
--------------------------------------------------------------------------------
1 | package tls
2 |
3 | import (
4 | "crypto/sha256"
5 | "encoding/base64"
6 | "encoding/pem"
7 | )
8 |
9 | func CalculatePEMCertChainSHA256Hash(certContent []byte) string {
10 | var certChain [][]byte
11 | for {
12 | block, remain := pem.Decode(certContent)
13 | if block == nil {
14 | break
15 | }
16 | certChain = append(certChain, block.Bytes)
17 | certContent = remain
18 | }
19 | certChainHash := GenerateCertChainHash(certChain)
20 | certChainHashB64 := base64.StdEncoding.EncodeToString(certChainHash)
21 | return certChainHashB64
22 | }
23 |
24 | func GenerateCertChainHash(rawCerts [][]byte) []byte {
25 | var hashValue []byte
26 | for _, certValue := range rawCerts {
27 | out := sha256.Sum256(certValue)
28 | if hashValue == nil {
29 | hashValue = out[:]
30 | } else {
31 | newHashValue := sha256.Sum256(append(hashValue, out[:]...))
32 | hashValue = newHashValue[:]
33 | }
34 | }
35 | return hashValue
36 | }
37 |
--------------------------------------------------------------------------------
/transport/internet/headers/noop/noop.go:
--------------------------------------------------------------------------------
1 | package noop
2 |
3 | import (
4 | "context"
5 | "net"
6 |
7 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
8 | )
9 |
10 | type Header struct{}
11 |
12 | func (Header) Size() int32 {
13 | return 0
14 | }
15 |
16 | // Serialize implements PacketHeader.
17 | func (Header) Serialize([]byte) {}
18 |
19 | func NewHeader(context.Context, interface{}) (interface{}, error) {
20 | return Header{}, nil
21 | }
22 |
23 | type ConnectionHeader struct{}
24 |
25 | func (ConnectionHeader) Client(conn net.Conn) net.Conn {
26 | return conn
27 | }
28 |
29 | func (ConnectionHeader) Server(conn net.Conn) net.Conn {
30 | return conn
31 | }
32 |
33 | func NewConnectionHeader(context.Context, interface{}) (interface{}, error) {
34 | return ConnectionHeader{}, nil
35 | }
36 |
37 | func init() {
38 | common.Must(common.RegisterConfig((*Config)(nil), NewHeader))
39 | common.Must(common.RegisterConfig((*ConnectionConfig)(nil), NewConnectionHeader))
40 | }
41 |
--------------------------------------------------------------------------------
/transport/internet/kcp/xor_amd64.s:
--------------------------------------------------------------------------------
1 | #include "textflag.h"
2 |
3 | // func xorfwd(x []byte)
4 | TEXT ·xorfwd(SB),NOSPLIT,$0
5 | MOVQ x+0(FP), SI // x[i]
6 | MOVQ x_len+8(FP), CX // x.len
7 | MOVQ x+0(FP), DI
8 | ADDQ $4, DI // x[i+4]
9 | SUBQ $4, CX
10 | xorfwdloop:
11 | MOVL (SI), AX
12 | XORL AX, (DI)
13 | ADDQ $4, SI
14 | ADDQ $4, DI
15 | SUBQ $4, CX
16 |
17 | CMPL CX, $0
18 | JE xorfwddone
19 |
20 | JMP xorfwdloop
21 | xorfwddone:
22 | RET
23 |
24 | // func xorbkd(x []byte)
25 | TEXT ·xorbkd(SB),NOSPLIT,$0
26 | MOVQ x+0(FP), SI
27 | MOVQ x_len+8(FP), CX // x.len
28 | MOVQ x+0(FP), DI
29 | ADDQ CX, SI // x[-8]
30 | SUBQ $8, SI
31 | ADDQ CX, DI // x[-4]
32 | SUBQ $4, DI
33 | SUBQ $4, CX
34 | xorbkdloop:
35 | MOVL (SI), AX
36 | XORL AX, (DI)
37 | SUBQ $4, SI
38 | SUBQ $4, DI
39 | SUBQ $4, CX
40 |
41 | CMPL CX, $0
42 | JE xorbkddone
43 |
44 | JMP xorbkdloop
45 |
46 | xorbkddone:
47 | RET
48 |
--------------------------------------------------------------------------------
/common/dice/dice_test.go:
--------------------------------------------------------------------------------
1 | package dice_test
2 |
3 | import (
4 | "math/rand"
5 | "testing"
6 |
7 | . "github.com/Shadowsocks-NET/v2ray-go/v4/common/dice"
8 | )
9 |
10 | func BenchmarkRoll1(b *testing.B) {
11 | for i := 0; i < b.N; i++ {
12 | Roll(1)
13 | }
14 | }
15 |
16 | func BenchmarkRoll20(b *testing.B) {
17 | for i := 0; i < b.N; i++ {
18 | Roll(20)
19 | }
20 | }
21 |
22 | func BenchmarkIntn1(b *testing.B) {
23 | for i := 0; i < b.N; i++ {
24 | rand.Intn(1)
25 | }
26 | }
27 |
28 | func BenchmarkIntn20(b *testing.B) {
29 | for i := 0; i < b.N; i++ {
30 | rand.Intn(20)
31 | }
32 | }
33 |
34 | func BenchmarkInt63(b *testing.B) {
35 | for i := 0; i < b.N; i++ {
36 | _ = uint16(rand.Int63() >> 47)
37 | }
38 | }
39 |
40 | func BenchmarkInt31(b *testing.B) {
41 | for i := 0; i < b.N; i++ {
42 | _ = uint16(rand.Int31() >> 15)
43 | }
44 | }
45 |
46 | func BenchmarkIntn(b *testing.B) {
47 | for i := 0; i < b.N; i++ {
48 | _ = uint16(rand.Intn(65536))
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/common/log/logger_test.go:
--------------------------------------------------------------------------------
1 | package log_test
2 |
3 | import (
4 | "os"
5 | "strings"
6 | "testing"
7 | "time"
8 |
9 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
10 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/buf"
11 | . "github.com/Shadowsocks-NET/v2ray-go/v4/common/log"
12 | )
13 |
14 | func TestFileLogger(t *testing.T) {
15 | f, err := os.CreateTemp("", "vtest")
16 | common.Must(err)
17 | path := f.Name()
18 | common.Must(f.Close())
19 |
20 | creator, err := CreateFileLogWriter(path)
21 | common.Must(err)
22 |
23 | handler := NewLogger(creator)
24 | handler.Handle(&GeneralMessage{Content: "Test Log"})
25 | time.Sleep(2 * time.Second)
26 |
27 | common.Must(common.Close(handler))
28 |
29 | f, err = os.Open(path)
30 | common.Must(err)
31 | defer f.Close()
32 |
33 | b, err := buf.ReadAllToBytes(f)
34 | common.Must(err)
35 | if !strings.Contains(string(b), "Test Log") {
36 | t.Fatal("Expect log text contains 'Test Log', but actually: ", string(b))
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/infra/conf/services.go:
--------------------------------------------------------------------------------
1 | package conf
2 |
3 | import (
4 | "encoding/json"
5 |
6 | "github.com/golang/protobuf/jsonpb"
7 | "github.com/jhump/protoreflect/desc"
8 | "github.com/jhump/protoreflect/dynamic"
9 |
10 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/serial"
11 | )
12 |
13 | func (c *Config) BuildServices(service map[string]*json.RawMessage) ([]*serial.TypedMessage, error) {
14 | var ret []*serial.TypedMessage
15 | for k, v := range service {
16 | message, err := desc.LoadMessageDescriptor(k)
17 | if err != nil || message == nil {
18 | return nil, newError("Cannot find service", k, "").Base(err)
19 | }
20 |
21 | serviceConfig := dynamic.NewMessage(message)
22 |
23 | if err := serviceConfig.UnmarshalJSONPB(&jsonpb.Unmarshaler{AllowUnknownFields: false}, *v); err != nil {
24 | return nil, newError("Cannot interpret service configure file", k, "").Base(err)
25 | }
26 |
27 | ret = append(ret, serial.ToTypedMessage(serviceConfig))
28 | }
29 | return ret, nil
30 | }
31 |
--------------------------------------------------------------------------------
/common/type_test.go:
--------------------------------------------------------------------------------
1 | package common_test
2 |
3 | import (
4 | "context"
5 | "testing"
6 |
7 | . "github.com/Shadowsocks-NET/v2ray-go/v4/common"
8 | )
9 |
10 | type TConfig struct {
11 | value int
12 | }
13 |
14 | type YConfig struct {
15 | value string
16 | }
17 |
18 | func TestObjectCreation(t *testing.T) {
19 | f := func(ctx context.Context, t interface{}) (interface{}, error) {
20 | return func() int {
21 | return t.(*TConfig).value
22 | }, nil
23 | }
24 |
25 | Must(RegisterConfig((*TConfig)(nil), f))
26 | err := RegisterConfig((*TConfig)(nil), f)
27 | if err == nil {
28 | t.Error("expect non-nil error, but got nil")
29 | }
30 |
31 | g, err := CreateObject(context.Background(), &TConfig{value: 2})
32 | Must(err)
33 | if v := g.(func() int)(); v != 2 {
34 | t.Error("expect return value 2, but got ", v)
35 | }
36 |
37 | _, err = CreateObject(context.Background(), &YConfig{value: "T"})
38 | if err == nil {
39 | t.Error("expect non-nil error, but got nil")
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/infra/conf/dokodemo_test.go:
--------------------------------------------------------------------------------
1 | package conf_test
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/net"
7 | . "github.com/Shadowsocks-NET/v2ray-go/v4/infra/conf"
8 | "github.com/Shadowsocks-NET/v2ray-go/v4/proxy/dokodemo"
9 | )
10 |
11 | func TestDokodemoConfig(t *testing.T) {
12 | creator := func() Buildable {
13 | return new(DokodemoConfig)
14 | }
15 |
16 | runMultiTestCase(t, []TestCase{
17 | {
18 | Input: `{
19 | "address": "8.8.8.8",
20 | "port": 53,
21 | "network": "tcp",
22 | "timeout": 10,
23 | "followRedirect": true,
24 | "userLevel": 1
25 | }`,
26 | Parser: loadJSON(creator),
27 | Output: &dokodemo.Config{
28 | Address: &net.IPOrDomain{
29 | Address: &net.IPOrDomain_Ip{
30 | Ip: []byte{8, 8, 8, 8},
31 | },
32 | },
33 | Port: 53,
34 | Networks: []net.Network{net.Network_TCP},
35 | FollowRedirect: true,
36 | UserLevel: 1,
37 | },
38 | },
39 | })
40 | }
41 |
--------------------------------------------------------------------------------
/proxy/shadowsocks/config.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package v2ray.core.proxy.shadowsocks;
4 | option csharp_namespace = "V2Ray.Core.Proxy.Shadowsocks";
5 | option go_package = "github.com/Shadowsocks-NET/v2ray-go/v4/proxy/shadowsocks";
6 | option java_package = "com.v2ray.core.proxy.shadowsocks";
7 | option java_multiple_files = true;
8 |
9 | import "common/net/network.proto";
10 | import "common/protocol/user.proto";
11 | import "common/protocol/server_spec.proto";
12 |
13 | message Account {
14 | string password = 1;
15 | CipherType cipher_type = 2;
16 |
17 | bool iv_check = 3;
18 | }
19 |
20 | enum CipherType {
21 | UNKNOWN = 0;
22 | AES_128_GCM = 1;
23 | AES_256_GCM = 2;
24 | CHACHA20_POLY1305 = 3;
25 | NONE = 4;
26 | }
27 |
28 | message ServerConfig {
29 | v2ray.core.common.protocol.User user = 2;
30 | repeated v2ray.core.common.net.Network network = 3;
31 | }
32 |
33 | message ClientConfig {
34 | repeated v2ray.core.common.protocol.ServerEndpoint server = 1;
35 | }
36 |
--------------------------------------------------------------------------------
/transport/internet/filelocker_other.go:
--------------------------------------------------------------------------------
1 | //go:build !windows
2 | // +build !windows
3 |
4 | package internet
5 |
6 | import (
7 | "os"
8 |
9 | "golang.org/x/sys/unix"
10 | )
11 |
12 | // Acquire lock
13 | func (fl *FileLocker) Acquire() error {
14 | f, err := os.Create(fl.path)
15 | if err != nil {
16 | return err
17 | }
18 | if err := unix.Flock(int(f.Fd()), unix.LOCK_EX); err != nil {
19 | f.Close()
20 | return newError("failed to lock file: ", fl.path).Base(err)
21 | }
22 | fl.file = f
23 | return nil
24 | }
25 |
26 | // Release lock
27 | func (fl *FileLocker) Release() {
28 | if err := unix.Flock(int(fl.file.Fd()), unix.LOCK_UN); err != nil {
29 | newError("failed to unlock file: ", fl.path).Base(err).WriteToLog()
30 | }
31 | if err := fl.file.Close(); err != nil {
32 | newError("failed to close file: ", fl.path).Base(err).WriteToLog()
33 | }
34 | if err := os.Remove(fl.path); err != nil {
35 | newError("failed to remove file: ", fl.path).Base(err).WriteToLog()
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/transport/internet/tcp/sockopt_linux_test.go:
--------------------------------------------------------------------------------
1 | //go:build linux
2 | // +build linux
3 |
4 | package tcp_test
5 |
6 | import (
7 | "context"
8 | "strings"
9 | "testing"
10 |
11 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
12 | "github.com/Shadowsocks-NET/v2ray-go/v4/testing/servers/tcp"
13 | "github.com/Shadowsocks-NET/v2ray-go/v4/transport/internet"
14 | . "github.com/Shadowsocks-NET/v2ray-go/v4/transport/internet/tcp"
15 | )
16 |
17 | func TestGetOriginalDestination(t *testing.T) {
18 | tcpServer := tcp.Server{}
19 | dest, err := tcpServer.Start()
20 | common.Must(err)
21 | defer tcpServer.Close()
22 |
23 | config, err := internet.ToMemoryStreamConfig(nil)
24 | common.Must(err)
25 | conn, err := Dial(context.Background(), dest, config)
26 | common.Must(err)
27 | defer conn.Close()
28 |
29 | originalDest, err := GetOriginalDestination(conn)
30 | if !(dest == originalDest || strings.Contains(err.Error(), "failed to call getsockopt")) {
31 | t.Error("unexpected state")
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/common/mux/session_test.go:
--------------------------------------------------------------------------------
1 | package mux_test
2 |
3 | import (
4 | "testing"
5 |
6 | . "github.com/Shadowsocks-NET/v2ray-go/v4/common/mux"
7 | )
8 |
9 | func TestSessionManagerAdd(t *testing.T) {
10 | m := NewSessionManager()
11 |
12 | s := m.Allocate()
13 | if s.ID != 1 {
14 | t.Error("id: ", s.ID)
15 | }
16 | if m.Size() != 1 {
17 | t.Error("size: ", m.Size())
18 | }
19 |
20 | s = m.Allocate()
21 | if s.ID != 2 {
22 | t.Error("id: ", s.ID)
23 | }
24 | if m.Size() != 2 {
25 | t.Error("size: ", m.Size())
26 | }
27 |
28 | s = &Session{
29 | ID: 4,
30 | }
31 | m.Add(s)
32 | if s.ID != 4 {
33 | t.Error("id: ", s.ID)
34 | }
35 | if m.Size() != 3 {
36 | t.Error("size: ", m.Size())
37 | }
38 | }
39 |
40 | func TestSessionManagerClose(t *testing.T) {
41 | m := NewSessionManager()
42 | s := m.Allocate()
43 |
44 | if m.CloseIfNoSession() {
45 | t.Error("able to close")
46 | }
47 | m.Remove(s.ID)
48 | if !m.CloseIfNoSession() {
49 | t.Error("not able to close")
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/testing/servers/http/http.go:
--------------------------------------------------------------------------------
1 | package tcp
2 |
3 | import (
4 | "net/http"
5 |
6 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/net"
7 | )
8 |
9 | type Server struct {
10 | Port net.Port
11 | PathHandler map[string]http.HandlerFunc
12 | server *http.Server
13 | }
14 |
15 | func (s *Server) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
16 | if req.URL.Path == "/" {
17 | resp.Header().Set("Content-Type", "text/plain; charset=utf-8")
18 | resp.WriteHeader(http.StatusOK)
19 | resp.Write([]byte("Home"))
20 | return
21 | }
22 |
23 | handler, found := s.PathHandler[req.URL.Path]
24 | if found {
25 | handler(resp, req)
26 | }
27 | }
28 |
29 | func (s *Server) Start() (net.Destination, error) {
30 | s.server = &http.Server{
31 | Addr: "127.0.0.1:" + s.Port.String(),
32 | Handler: s,
33 | }
34 | go s.server.ListenAndServe()
35 | return net.TCPDestination(net.LocalHostIP, s.Port), nil
36 | }
37 |
38 | func (s *Server) Close() error {
39 | return s.server.Close()
40 | }
41 |
--------------------------------------------------------------------------------
/transport/internet/kcp/connection_test.go:
--------------------------------------------------------------------------------
1 | package kcp_test
2 |
3 | import (
4 | "io"
5 | "testing"
6 | "time"
7 |
8 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/buf"
9 | . "github.com/Shadowsocks-NET/v2ray-go/v4/transport/internet/kcp"
10 | )
11 |
12 | type NoOpCloser int
13 |
14 | func (NoOpCloser) Close() error {
15 | return nil
16 | }
17 |
18 | func TestConnectionReadTimeout(t *testing.T) {
19 | conn := NewConnection(ConnMetadata{Conversation: 1}, &KCPPacketWriter{
20 | Writer: buf.DiscardBytes,
21 | }, NoOpCloser(0), &Config{})
22 | conn.SetReadDeadline(time.Now().Add(time.Second))
23 |
24 | b := make([]byte, 1024)
25 | nBytes, err := conn.Read(b)
26 | if nBytes != 0 || err == nil {
27 | t.Error("unexpected read: ", nBytes, err)
28 | }
29 |
30 | conn.Terminate()
31 | }
32 |
33 | func TestConnectionInterface(t *testing.T) {
34 | _ = (io.Writer)(new(Connection))
35 | _ = (io.Reader)(new(Connection))
36 | _ = (buf.Reader)(new(Connection))
37 | _ = (buf.Writer)(new(Connection))
38 | }
39 |
--------------------------------------------------------------------------------
/common/common_test.go:
--------------------------------------------------------------------------------
1 | package common_test
2 |
3 | import (
4 | "errors"
5 | "testing"
6 |
7 | . "github.com/Shadowsocks-NET/v2ray-go/v4/common"
8 | )
9 |
10 | func TestMust(t *testing.T) {
11 | hasPanic := func(f func()) (ret bool) {
12 | defer func() {
13 | if r := recover(); r != nil {
14 | ret = true
15 | }
16 | }()
17 | f()
18 | return false
19 | }
20 |
21 | testCases := []struct {
22 | Input func()
23 | Panic bool
24 | }{
25 | {
26 | Panic: true,
27 | Input: func() { Must(func() error { return errors.New("test error") }()) },
28 | },
29 | {
30 | Panic: true,
31 | Input: func() { Must2(func() (int, error) { return 0, errors.New("test error") }()) },
32 | },
33 | {
34 | Panic: false,
35 | Input: func() { Must(func() error { return nil }()) },
36 | },
37 | }
38 |
39 | for idx, test := range testCases {
40 | if hasPanic(test.Input) != test.Panic {
41 | t.Error("test case #", idx, " expect panic ", test.Panic, " but actually not")
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/transport/internet/kcp/crypt_test.go:
--------------------------------------------------------------------------------
1 | package kcp_test
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/google/go-cmp/cmp"
7 |
8 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
9 | . "github.com/Shadowsocks-NET/v2ray-go/v4/transport/internet/kcp"
10 | )
11 |
12 | func TestSimpleAuthenticator(t *testing.T) {
13 | cache := make([]byte, 512)
14 |
15 | payload := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g'}
16 |
17 | auth := NewSimpleAuthenticator()
18 | b := auth.Seal(cache[:0], nil, payload, nil)
19 | c, err := auth.Open(cache[:0], nil, b, nil)
20 | common.Must(err)
21 | if r := cmp.Diff(c, payload); r != "" {
22 | t.Error(r)
23 | }
24 | }
25 |
26 | func TestSimpleAuthenticator2(t *testing.T) {
27 | cache := make([]byte, 512)
28 |
29 | payload := []byte{'a', 'b'}
30 |
31 | auth := NewSimpleAuthenticator()
32 | b := auth.Seal(cache[:0], nil, payload, nil)
33 | c, err := auth.Open(cache[:0], nil, b, nil)
34 | common.Must(err)
35 | if r := cmp.Diff(c, payload); r != "" {
36 | t.Error(r)
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/transport/internet/domainsocket/config.go:
--------------------------------------------------------------------------------
1 | //go:build !confonly
2 | // +build !confonly
3 |
4 | package domainsocket
5 |
6 | import (
7 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
8 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/net"
9 | "github.com/Shadowsocks-NET/v2ray-go/v4/transport/internet"
10 | )
11 |
12 | const (
13 | protocolName = "domainsocket"
14 | sizeofSunPath = 108
15 | )
16 |
17 | func (c *Config) GetUnixAddr() (*net.UnixAddr, error) {
18 | path := c.Path
19 | if path == "" {
20 | return nil, newError("empty domain socket path")
21 | }
22 | if c.Abstract && path[0] != '@' {
23 | path = "@" + path
24 | }
25 | if c.Abstract && c.Padding {
26 | raw := []byte(path)
27 | addr := make([]byte, sizeofSunPath)
28 | copy(addr, raw)
29 | path = string(addr)
30 | }
31 | return &net.UnixAddr{
32 | Name: path,
33 | Net: "unix",
34 | }, nil
35 | }
36 |
37 | func init() {
38 | common.Must(internet.RegisterProtocolConfigCreator(protocolName, func() interface{} {
39 | return new(Config)
40 | }))
41 | }
42 |
--------------------------------------------------------------------------------
/transport/internet/headers/wechat/wechat.go:
--------------------------------------------------------------------------------
1 | package wechat
2 |
3 | import (
4 | "context"
5 | "encoding/binary"
6 |
7 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
8 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/dice"
9 | )
10 |
11 | type VideoChat struct {
12 | sn uint32
13 | }
14 |
15 | func (vc *VideoChat) Size() int32 {
16 | return 13
17 | }
18 |
19 | // Serialize implements PacketHeader.
20 | func (vc *VideoChat) Serialize(b []byte) {
21 | vc.sn++
22 | b[0] = 0xa1
23 | b[1] = 0x08
24 | binary.BigEndian.PutUint32(b[2:], vc.sn) // b[2:6]
25 | b[6] = 0x00
26 | b[7] = 0x10
27 | b[8] = 0x11
28 | b[9] = 0x18
29 | b[10] = 0x30
30 | b[11] = 0x22
31 | b[12] = 0x30
32 | }
33 |
34 | // NewVideoChat returns a new VideoChat instance based on given config.
35 | func NewVideoChat(ctx context.Context, config interface{}) (interface{}, error) {
36 | return &VideoChat{
37 | sn: uint32(dice.RollUint16()),
38 | }, nil
39 | }
40 |
41 | func init() {
42 | common.Must(common.RegisterConfig((*VideoConfig)(nil), NewVideoChat))
43 | }
44 |
--------------------------------------------------------------------------------
/infra/conf/reverse_test.go:
--------------------------------------------------------------------------------
1 | package conf_test
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/Shadowsocks-NET/v2ray-go/v4/app/reverse"
7 | "github.com/Shadowsocks-NET/v2ray-go/v4/infra/conf"
8 | )
9 |
10 | func TestReverseConfig(t *testing.T) {
11 | creator := func() conf.Buildable {
12 | return new(conf.ReverseConfig)
13 | }
14 |
15 | runMultiTestCase(t, []TestCase{
16 | {
17 | Input: `{
18 | "bridges": [{
19 | "tag": "test",
20 | "domain": "test.v2fly.org"
21 | }]
22 | }`,
23 | Parser: loadJSON(creator),
24 | Output: &reverse.Config{
25 | BridgeConfig: []*reverse.BridgeConfig{
26 | {Tag: "test", Domain: "test.v2fly.org"},
27 | },
28 | },
29 | },
30 | {
31 | Input: `{
32 | "portals": [{
33 | "tag": "test",
34 | "domain": "test.v2fly.org"
35 | }]
36 | }`,
37 | Parser: loadJSON(creator),
38 | Output: &reverse.Config{
39 | PortalConfig: []*reverse.PortalConfig{
40 | {Tag: "test", Domain: "test.v2fly.org"},
41 | },
42 | },
43 | },
44 | })
45 | }
46 |
--------------------------------------------------------------------------------
/common/task/periodic_test.go:
--------------------------------------------------------------------------------
1 | package task_test
2 |
3 | import (
4 | "sync/atomic"
5 | "testing"
6 | "time"
7 |
8 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
9 | . "github.com/Shadowsocks-NET/v2ray-go/v4/common/task"
10 | )
11 |
12 | func TestPeriodicTaskStop(t *testing.T) {
13 | var value uint64
14 | task := &Periodic{
15 | Interval: time.Second * 2,
16 | Execute: func() error {
17 | atomic.AddUint64(&value, 1)
18 | return nil
19 | },
20 | }
21 | common.Must(task.Start())
22 | time.Sleep(time.Second * 5)
23 | common.Must(task.Close())
24 | value1 := atomic.LoadUint64(&value)
25 | if value1 != 3 {
26 | t.Fatal("expected 3, but got ", value1)
27 | }
28 |
29 | time.Sleep(time.Second * 4)
30 | value2 := atomic.LoadUint64(&value)
31 | if value2 != 3 {
32 | t.Fatal("expected 3, but got ", value2)
33 | }
34 |
35 | common.Must(task.Start())
36 | time.Sleep(time.Second * 3)
37 | value3 := atomic.LoadUint64(&value)
38 | if value3 != 5 {
39 | t.Fatal("Expected 5, but ", value3)
40 | }
41 | common.Must(task.Close())
42 | }
43 |
--------------------------------------------------------------------------------
/transport/internet/header.go:
--------------------------------------------------------------------------------
1 | package internet
2 |
3 | import (
4 | "context"
5 | "net"
6 |
7 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
8 | )
9 |
10 | type PacketHeader interface {
11 | Size() int32
12 | Serialize([]byte)
13 | }
14 |
15 | func CreatePacketHeader(config interface{}) (PacketHeader, error) {
16 | header, err := common.CreateObject(context.Background(), config)
17 | if err != nil {
18 | return nil, err
19 | }
20 | if h, ok := header.(PacketHeader); ok {
21 | return h, nil
22 | }
23 | return nil, newError("not a packet header")
24 | }
25 |
26 | type ConnectionAuthenticator interface {
27 | Client(net.Conn) net.Conn
28 | Server(net.Conn) net.Conn
29 | }
30 |
31 | func CreateConnectionAuthenticator(config interface{}) (ConnectionAuthenticator, error) {
32 | auth, err := common.CreateObject(context.Background(), config)
33 | if err != nil {
34 | return nil, err
35 | }
36 | if a, ok := auth.(ConnectionAuthenticator); ok {
37 | return a, nil
38 | }
39 | return nil, newError("not a ConnectionAuthenticator")
40 | }
41 |
--------------------------------------------------------------------------------
/common/buf/readv_posix.go:
--------------------------------------------------------------------------------
1 | //go:build !windows && !wasm && !illumos
2 | // +build !windows,!wasm,!illumos
3 |
4 | package buf
5 |
6 | import (
7 | "syscall"
8 | "unsafe"
9 | )
10 |
11 | type posixReader struct {
12 | iovecs []syscall.Iovec
13 | }
14 |
15 | func (r *posixReader) Init(bs []*Buffer) {
16 | iovecs := r.iovecs
17 | if iovecs == nil {
18 | iovecs = make([]syscall.Iovec, 0, len(bs))
19 | }
20 | for idx, b := range bs {
21 | iovecs = append(iovecs, syscall.Iovec{
22 | Base: &(b.v[0]),
23 | })
24 | iovecs[idx].SetLen(int(Size))
25 | }
26 | r.iovecs = iovecs
27 | }
28 |
29 | func (r *posixReader) Read(fd uintptr) int32 {
30 | n, _, e := syscall.Syscall(syscall.SYS_READV, fd, uintptr(unsafe.Pointer(&r.iovecs[0])), uintptr(len(r.iovecs)))
31 | if e != 0 {
32 | return -1
33 | }
34 | return int32(n)
35 | }
36 |
37 | func (r *posixReader) Clear() {
38 | for idx := range r.iovecs {
39 | r.iovecs[idx].Base = nil
40 | }
41 | r.iovecs = r.iovecs[:0]
42 | }
43 |
44 | func newMultiReader() multiReader {
45 | return &posixReader{}
46 | }
47 |
--------------------------------------------------------------------------------
/common/signal/done/done.go:
--------------------------------------------------------------------------------
1 | package done
2 |
3 | import (
4 | "sync"
5 | )
6 |
7 | // Instance is a utility for notifications of something being done.
8 | type Instance struct {
9 | access sync.Mutex
10 | c chan struct{}
11 | closed bool
12 | }
13 |
14 | // New returns a new Done.
15 | func New() *Instance {
16 | return &Instance{
17 | c: make(chan struct{}),
18 | }
19 | }
20 |
21 | // Done returns true if Close() is called.
22 | func (d *Instance) Done() bool {
23 | select {
24 | case <-d.Wait():
25 | return true
26 | default:
27 | return false
28 | }
29 | }
30 |
31 | // Wait returns a channel for waiting for done.
32 | func (d *Instance) Wait() <-chan struct{} {
33 | return d.c
34 | }
35 |
36 | // Close marks this Done 'done'. This method may be called multiple times. All calls after first call will have no effect on its status.
37 | func (d *Instance) Close() error {
38 | d.access.Lock()
39 | defer d.access.Unlock()
40 |
41 | if d.closed {
42 | return nil
43 | }
44 |
45 | d.closed = true
46 | close(d.c)
47 |
48 | return nil
49 | }
50 |
--------------------------------------------------------------------------------
/infra/conf/freedom_test.go:
--------------------------------------------------------------------------------
1 | package conf_test
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/net"
7 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/protocol"
8 | . "github.com/Shadowsocks-NET/v2ray-go/v4/infra/conf"
9 | "github.com/Shadowsocks-NET/v2ray-go/v4/proxy/freedom"
10 | )
11 |
12 | func TestFreedomConfig(t *testing.T) {
13 | creator := func() Buildable {
14 | return new(FreedomConfig)
15 | }
16 |
17 | runMultiTestCase(t, []TestCase{
18 | {
19 | Input: `{
20 | "domainStrategy": "AsIs",
21 | "timeout": 10,
22 | "redirect": "127.0.0.1:3366",
23 | "userLevel": 1
24 | }`,
25 | Parser: loadJSON(creator),
26 | Output: &freedom.Config{
27 | DestinationOverride: &freedom.DestinationOverride{
28 | Server: &protocol.ServerEndpoint{
29 | Address: &net.IPOrDomain{
30 | Address: &net.IPOrDomain_Ip{
31 | Ip: []byte{127, 0, 0, 1},
32 | },
33 | },
34 | Port: 3366,
35 | },
36 | },
37 | UserLevel: 1,
38 | },
39 | },
40 | })
41 | }
42 |
--------------------------------------------------------------------------------
/app/dispatcher/stats_test.go:
--------------------------------------------------------------------------------
1 | package dispatcher_test
2 |
3 | import (
4 | "testing"
5 |
6 | . "github.com/Shadowsocks-NET/v2ray-go/v4/app/dispatcher"
7 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
8 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/buf"
9 | )
10 |
11 | type TestCounter int64
12 |
13 | func (c *TestCounter) Value() int64 {
14 | return int64(*c)
15 | }
16 |
17 | func (c *TestCounter) Add(v int64) int64 {
18 | x := int64(*c) + v
19 | *c = TestCounter(x)
20 | return x
21 | }
22 |
23 | func (c *TestCounter) Set(v int64) int64 {
24 | *c = TestCounter(v)
25 | return v
26 | }
27 |
28 | func TestStatsWriter(t *testing.T) {
29 | var c TestCounter
30 | writer := &SizeStatWriter{
31 | Counter: &c,
32 | Writer: buf.Discard,
33 | }
34 |
35 | mb := buf.MergeBytes(nil, []byte("abcd"))
36 | common.Must(writer.WriteMultiBuffer(mb))
37 |
38 | mb = buf.MergeBytes(nil, []byte("efg"))
39 | common.Must(writer.WriteMultiBuffer(mb))
40 |
41 | if c.Value() != 7 {
42 | t.Fatal("unexpected counter value. want 7, but got ", c.Value())
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/infra/conf/shadowsocks_test.go:
--------------------------------------------------------------------------------
1 | package conf_test
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/net"
7 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/protocol"
8 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/serial"
9 | . "github.com/Shadowsocks-NET/v2ray-go/v4/infra/conf"
10 | "github.com/Shadowsocks-NET/v2ray-go/v4/proxy/shadowsocks"
11 | )
12 |
13 | func TestShadowsocksServerConfigParsing(t *testing.T) {
14 | creator := func() Buildable {
15 | return new(ShadowsocksServerConfig)
16 | }
17 |
18 | runMultiTestCase(t, []TestCase{
19 | {
20 | Input: `{
21 | "method": "aes-256-GCM",
22 | "password": "v2ray-password"
23 | }`,
24 | Parser: loadJSON(creator),
25 | Output: &shadowsocks.ServerConfig{
26 | User: &protocol.User{
27 | Account: serial.ToTypedMessage(&shadowsocks.Account{
28 | CipherType: shadowsocks.CipherType_AES_256_GCM,
29 | Password: "v2ray-password",
30 | }),
31 | },
32 | Network: []net.Network{net.Network_TCP},
33 | },
34 | },
35 | })
36 | }
37 |
--------------------------------------------------------------------------------
/common/protocol/user.go:
--------------------------------------------------------------------------------
1 | package protocol
2 |
3 | func (u *User) GetTypedAccount() (Account, error) {
4 | if u.GetAccount() == nil {
5 | return nil, newError("Account missing").AtWarning()
6 | }
7 |
8 | rawAccount, err := u.Account.GetInstance()
9 | if err != nil {
10 | return nil, err
11 | }
12 | if asAccount, ok := rawAccount.(AsAccount); ok {
13 | return asAccount.AsAccount()
14 | }
15 | if account, ok := rawAccount.(Account); ok {
16 | return account, nil
17 | }
18 | return nil, newError("Unknown account type: ", u.Account.Type)
19 | }
20 |
21 | func (u *User) ToMemoryUser() (*MemoryUser, error) {
22 | account, err := u.GetTypedAccount()
23 | if err != nil {
24 | return nil, err
25 | }
26 | return &MemoryUser{
27 | Account: account,
28 | Email: u.Email,
29 | Level: u.Level,
30 | }, nil
31 | }
32 |
33 | // MemoryUser is a parsed form of User, to reduce number of parsing of Account proto.
34 | type MemoryUser struct {
35 | // Account is the parsed account of the protocol.
36 | Account Account
37 | Email string
38 | Level uint32
39 | }
40 |
--------------------------------------------------------------------------------
/release/requestsign.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | RELEASE_DATA=$(curl --data "version=${SIGN_VERSION}" --data "password=${SIGN_SERVICE_PASSWORD}" -X POST "${SIGN_SERIVCE_URL}" )
4 | echo $RELEASE_DATA
5 | RELEASE_ID=$(echo $RELEASE_DATA| jq -r ".id")
6 |
7 | function uploadfile() {
8 | FILE=$1
9 | CTYPE=$(file -b --mime-type $FILE)
10 |
11 | sleep 1
12 | curl -H "Authorization: token ${GITHUB_TOKEN}" -H "Content-Type: ${CTYPE}" --data-binary @$FILE "https://uploads.github.com/repos/v2fly/v2ray-core/releases/${RELEASE_ID}/assets?name=$(basename $FILE)"
13 | sleep 1
14 | }
15 |
16 | function upload() {
17 | FILE=$1
18 | DGST=$1.dgst
19 | openssl dgst -md5 $FILE | sed 's/([^)]*)//g' >> $DGST
20 | openssl dgst -sha1 $FILE | sed 's/([^)]*)//g' >> $DGST
21 | openssl dgst -sha256 $FILE | sed 's/([^)]*)//g' >> $DGST
22 | openssl dgst -sha512 $FILE | sed 's/([^)]*)//g' >> $DGST
23 | uploadfile $FILE
24 | uploadfile $DGST
25 | }
26 |
27 | curl "https://raw.githubusercontent.com/v2fly/Release/master/v2fly/${SIGN_VERSION}.Release" > Release
28 | upload Release
29 |
--------------------------------------------------------------------------------
/infra/conf/general_test.go:
--------------------------------------------------------------------------------
1 | package conf_test
2 |
3 | import (
4 | "encoding/json"
5 | "testing"
6 |
7 | "github.com/golang/protobuf/proto"
8 |
9 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
10 | . "github.com/Shadowsocks-NET/v2ray-go/v4/infra/conf"
11 | )
12 |
13 | func loadJSON(creator func() Buildable) func(string) (proto.Message, error) {
14 | return func(s string) (proto.Message, error) {
15 | instance := creator()
16 | if err := json.Unmarshal([]byte(s), instance); err != nil {
17 | return nil, err
18 | }
19 | return instance.Build()
20 | }
21 | }
22 |
23 | type TestCase struct {
24 | Input string
25 | Parser func(string) (proto.Message, error)
26 | Output proto.Message
27 | }
28 |
29 | func runMultiTestCase(t *testing.T, testCases []TestCase) {
30 | for _, testCase := range testCases {
31 | actual, err := testCase.Parser(testCase.Input)
32 | common.Must(err)
33 | if !proto.Equal(actual, testCase.Output) {
34 | t.Fatalf("Failed in test case:\n%s\nActual:\n%v\nExpected:\n%v", testCase.Input, actual, testCase.Output)
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/infra/control/command.go:
--------------------------------------------------------------------------------
1 | package control
2 |
3 | import (
4 | "fmt"
5 | "log"
6 | "os"
7 | "strings"
8 | )
9 |
10 | type Description struct {
11 | Short string
12 | Usage []string
13 | }
14 |
15 | type Command interface {
16 | Name() string
17 | Description() Description
18 | Execute(args []string) error
19 | }
20 |
21 | var (
22 | commandRegistry = make(map[string]Command)
23 | ctllog = log.New(os.Stderr, "v2ctl> ", 0)
24 | )
25 |
26 | func RegisterCommand(cmd Command) error {
27 | entry := strings.ToLower(cmd.Name())
28 | if entry == "" {
29 | return newError("empty command name")
30 | }
31 | commandRegistry[entry] = cmd
32 | return nil
33 | }
34 |
35 | func GetCommand(name string) Command {
36 | cmd, found := commandRegistry[name]
37 | if !found {
38 | return nil
39 | }
40 | return cmd
41 | }
42 |
43 | type hiddenCommand interface {
44 | Hidden() bool
45 | }
46 |
47 | func PrintUsage() {
48 | for name, cmd := range commandRegistry {
49 | if _, ok := cmd.(hiddenCommand); ok {
50 | continue
51 | }
52 | fmt.Println(" ", name, "\t\t\t", cmd.Description())
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/testing/scenarios/common_coverage.go:
--------------------------------------------------------------------------------
1 | //go:build coverage
2 | // +build coverage
3 |
4 | package scenarios
5 |
6 | import (
7 | "bytes"
8 | "os"
9 | "os/exec"
10 |
11 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/uuid"
12 | )
13 |
14 | func BuildV2Ray() error {
15 | genTestBinaryPath()
16 | if _, err := os.Stat(testBinaryPath); err == nil {
17 | return nil
18 | }
19 |
20 | cmd := exec.Command("go", "test", "-tags", "coverage coveragemain", "-coverpkg", "github.com/Shadowsocks-NET/v2ray-go/v4/...", "-c", "-o", testBinaryPath, GetSourcePath())
21 | return cmd.Run()
22 | }
23 |
24 | func RunV2RayProtobuf(config []byte) *exec.Cmd {
25 | genTestBinaryPath()
26 |
27 | covDir := os.Getenv("V2RAY_COV")
28 | os.MkdirAll(covDir, os.ModeDir)
29 | randomID := uuid.New()
30 | profile := randomID.String() + ".out"
31 | proc := exec.Command(testBinaryPath, "-config=stdin:", "-format=pb", "-test.run", "TestRunMainForCoverage", "-test.coverprofile", profile, "-test.outputdir", covDir)
32 | proc.Stdin = bytes.NewBuffer(config)
33 | proc.Stderr = os.Stderr
34 | proc.Stdout = os.Stdout
35 |
36 | return proc
37 | }
38 |
--------------------------------------------------------------------------------
/transport/internet/udp/hub_linux.go:
--------------------------------------------------------------------------------
1 | //go:build linux
2 | // +build linux
3 |
4 | package udp
5 |
6 | import (
7 | "syscall"
8 |
9 | "golang.org/x/sys/unix"
10 |
11 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/net"
12 | )
13 |
14 | func RetrieveOriginalDest(oob []byte) net.Destination {
15 | msgs, err := syscall.ParseSocketControlMessage(oob)
16 | if err != nil {
17 | return net.Destination{}
18 | }
19 | for _, msg := range msgs {
20 | if msg.Header.Level == syscall.SOL_IP && msg.Header.Type == syscall.IP_RECVORIGDSTADDR {
21 | ip := net.IPAddress(msg.Data[4:8])
22 | port := net.PortFromBytes(msg.Data[2:4])
23 | return net.UDPDestination(ip, port)
24 | } else if msg.Header.Level == syscall.SOL_IPV6 && msg.Header.Type == unix.IPV6_RECVORIGDSTADDR {
25 | ip := net.IPAddress(msg.Data[8:24])
26 | port := net.PortFromBytes(msg.Data[2:4])
27 | return net.UDPDestination(ip, port)
28 | }
29 | }
30 | return net.Destination{}
31 | }
32 |
33 | func ReadUDPMsg(conn *net.UDPConn, payload []byte, oob []byte) (int, int, int, *net.UDPAddr, error) {
34 | return conn.ReadMsgUDP(payload, oob)
35 | }
36 |
--------------------------------------------------------------------------------
/proxy/shadowsocks/config_test.go:
--------------------------------------------------------------------------------
1 | package shadowsocks_test
2 |
3 | import (
4 | "crypto/rand"
5 | "testing"
6 |
7 | "github.com/google/go-cmp/cmp"
8 |
9 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
10 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/buf"
11 | "github.com/Shadowsocks-NET/v2ray-go/v4/proxy/shadowsocks"
12 | )
13 |
14 | func TestAEADCipherUDP(t *testing.T) {
15 | rawAccount := &shadowsocks.Account{
16 | CipherType: shadowsocks.CipherType_AES_128_GCM,
17 | Password: "test",
18 | }
19 | account, err := rawAccount.AsAccount()
20 | common.Must(err)
21 |
22 | cipher := account.(*shadowsocks.MemoryAccount).Cipher
23 |
24 | key := make([]byte, cipher.KeySize())
25 | common.Must2(rand.Read(key))
26 |
27 | payload := make([]byte, 1024)
28 | common.Must2(rand.Read(payload))
29 |
30 | b1 := buf.New()
31 | common.Must2(b1.ReadFullFrom(rand.Reader, cipher.IVSize()))
32 | common.Must2(b1.Write(payload))
33 | common.Must(cipher.EncodePacket(key, b1))
34 |
35 | common.Must(cipher.DecodePacket(key, b1))
36 | if diff := cmp.Diff(b1.Bytes(), payload); diff != "" {
37 | t.Error(diff)
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/common/task/task.go:
--------------------------------------------------------------------------------
1 | package task
2 |
3 | import (
4 | "context"
5 |
6 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/signal/semaphore"
7 | )
8 |
9 | // OnSuccess executes g() after f() returns nil.
10 | func OnSuccess(f func() error, g func() error) func() error {
11 | return func() error {
12 | if err := f(); err != nil {
13 | return err
14 | }
15 | return g()
16 | }
17 | }
18 |
19 | // Run executes a list of tasks in parallel, returns the first error encountered or nil if all tasks pass.
20 | func Run(ctx context.Context, tasks ...func() error) error {
21 | n := len(tasks)
22 | s := semaphore.New(n)
23 | done := make(chan error, 1)
24 |
25 | for _, task := range tasks {
26 | <-s.Wait()
27 | go func(f func() error) {
28 | err := f()
29 | if err == nil {
30 | s.Signal()
31 | return
32 | }
33 |
34 | select {
35 | case done <- err:
36 | default:
37 | }
38 | }(task)
39 | }
40 |
41 | for i := 0; i < n; i++ {
42 | select {
43 | case err := <-done:
44 | return err
45 | case <-ctx.Done():
46 | return ctx.Err()
47 | case <-s.Wait():
48 | }
49 | }
50 |
51 | return nil
52 | }
53 |
--------------------------------------------------------------------------------
/transport/internet/sockopt_test.go:
--------------------------------------------------------------------------------
1 | package internet_test
2 |
3 | import (
4 | "context"
5 | "testing"
6 |
7 | "github.com/google/go-cmp/cmp"
8 |
9 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
10 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/buf"
11 | "github.com/Shadowsocks-NET/v2ray-go/v4/testing/servers/tcp"
12 | . "github.com/Shadowsocks-NET/v2ray-go/v4/transport/internet"
13 | )
14 |
15 | func TestTCPFastOpen(t *testing.T) {
16 | tcpServer := tcp.Server{
17 | MsgProcessor: func(b []byte) []byte {
18 | return b
19 | },
20 | }
21 | dest, err := tcpServer.StartContext(context.Background(), &SocketConfig{Tfo: SocketConfig_Enable})
22 | common.Must(err)
23 | defer tcpServer.Close()
24 |
25 | ctx := context.Background()
26 | dialer := DefaultSystemDialer{}
27 | conn, err := dialer.Dial(ctx, nil, dest, &SocketConfig{
28 | Tfo: SocketConfig_Enable,
29 | })
30 | common.Must(err)
31 | defer conn.Close()
32 |
33 | _, err = conn.Write([]byte("abcd"))
34 | common.Must(err)
35 |
36 | b := buf.New()
37 | common.Must2(b.ReadFrom(conn))
38 | if r := cmp.Diff(b.Bytes(), []byte("abcd")); r != "" {
39 | t.Fatal(r)
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/common/protocol/tls/cert/privateKey.go:
--------------------------------------------------------------------------------
1 | package cert
2 |
3 | import (
4 | "crypto/x509/pkix"
5 | "encoding/asn1"
6 | "math/big"
7 | )
8 |
9 | type ecPrivateKey struct {
10 | Version int
11 | PrivateKey []byte
12 | NamedCurveOID asn1.ObjectIdentifier `asn1:"optional,explicit,tag:0"`
13 | PublicKey asn1.BitString `asn1:"optional,explicit,tag:1"`
14 | }
15 |
16 | type pkcs8 struct {
17 | Version int
18 | Algo pkix.AlgorithmIdentifier
19 | PrivateKey []byte
20 | // optional attributes omitted.
21 | }
22 |
23 | type pkcs1AdditionalRSAPrime struct {
24 | Prime *big.Int
25 |
26 | // We ignore these values because rsa will calculate them.
27 | Exp *big.Int
28 | Coeff *big.Int
29 | }
30 |
31 | type pkcs1PrivateKey struct {
32 | Version int
33 | N *big.Int
34 | E int
35 | D *big.Int
36 | P *big.Int
37 | Q *big.Int
38 | // We ignore these values, if present, because rsa will calculate them.
39 | Dp *big.Int `asn1:"optional"`
40 | Dq *big.Int `asn1:"optional"`
41 | Qinv *big.Int `asn1:"optional"`
42 |
43 | AdditionalPrimes []pkcs1AdditionalRSAPrime `asn1:"optional,omitempty"`
44 | }
45 |
--------------------------------------------------------------------------------
/transport/internet/http/config.go:
--------------------------------------------------------------------------------
1 | //go:build !confonly
2 | // +build !confonly
3 |
4 | package http
5 |
6 | import (
7 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
8 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/dice"
9 | "github.com/Shadowsocks-NET/v2ray-go/v4/transport/internet"
10 | )
11 |
12 | const protocolName = "http"
13 |
14 | func (c *Config) getHosts() []string {
15 | if len(c.Host) == 0 {
16 | return []string{"www.example.com"}
17 | }
18 | return c.Host
19 | }
20 |
21 | func (c *Config) isValidHost(host string) bool {
22 | hosts := c.getHosts()
23 | for _, h := range hosts {
24 | if h == host {
25 | return true
26 | }
27 | }
28 | return false
29 | }
30 |
31 | func (c *Config) getRandomHost() string {
32 | hosts := c.getHosts()
33 | return hosts[dice.Roll(len(hosts))]
34 | }
35 |
36 | func (c *Config) getNormalizedPath() string {
37 | if c.Path == "" {
38 | return "/"
39 | }
40 | if c.Path[0] != '/' {
41 | return "/" + c.Path
42 | }
43 | return c.Path
44 | }
45 |
46 | func init() {
47 | common.Must(internet.RegisterProtocolConfigCreator(protocolName, func() interface{} {
48 | return new(Config)
49 | }))
50 | }
51 |
--------------------------------------------------------------------------------
/common/strmatcher/full_matcher_test.go:
--------------------------------------------------------------------------------
1 | package strmatcher_test
2 |
3 | import (
4 | "reflect"
5 | "testing"
6 |
7 | . "github.com/Shadowsocks-NET/v2ray-go/v4/common/strmatcher"
8 | )
9 |
10 | func TestFullMatcherGroup(t *testing.T) {
11 | g := new(FullMatcherGroup)
12 | g.Add("v2fly.org", 1)
13 | g.Add("google.com", 2)
14 | g.Add("x.a.com", 3)
15 | g.Add("x.y.com", 4)
16 | g.Add("x.y.com", 6)
17 |
18 | testCases := []struct {
19 | Domain string
20 | Result []uint32
21 | }{
22 | {
23 | Domain: "v2fly.org",
24 | Result: []uint32{1},
25 | },
26 | {
27 | Domain: "y.com",
28 | Result: nil,
29 | },
30 | {
31 | Domain: "x.y.com",
32 | Result: []uint32{4, 6},
33 | },
34 | }
35 |
36 | for _, testCase := range testCases {
37 | r := g.Match(testCase.Domain)
38 | if !reflect.DeepEqual(r, testCase.Result) {
39 | t.Error("Failed to match domain: ", testCase.Domain, ", expect ", testCase.Result, ", but got ", r)
40 | }
41 | }
42 | }
43 |
44 | func TestEmptyFullMatcherGroup(t *testing.T) {
45 | g := new(FullMatcherGroup)
46 | r := g.Match("v2fly.org")
47 | if len(r) != 0 {
48 | t.Error("Expect [], but ", r)
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/transport/internet/memory_settings.go:
--------------------------------------------------------------------------------
1 | package internet
2 |
3 | // MemoryStreamConfig is a parsed form of StreamConfig. This is used to reduce number of Protobuf parsing.
4 | type MemoryStreamConfig struct {
5 | ProtocolName string
6 | ProtocolSettings interface{}
7 | SecurityType string
8 | SecuritySettings interface{}
9 | SocketSettings *SocketConfig
10 | }
11 |
12 | // ToMemoryStreamConfig converts a StreamConfig to MemoryStreamConfig. It returns a default non-nil MemoryStreamConfig for nil input.
13 | func ToMemoryStreamConfig(s *StreamConfig) (*MemoryStreamConfig, error) {
14 | ets, err := s.GetEffectiveTransportSettings()
15 | if err != nil {
16 | return nil, err
17 | }
18 |
19 | mss := &MemoryStreamConfig{
20 | ProtocolName: s.GetEffectiveProtocol(),
21 | ProtocolSettings: ets,
22 | }
23 |
24 | if s != nil {
25 | mss.SocketSettings = s.SocketSettings
26 | }
27 |
28 | if s != nil && s.HasSecuritySettings() {
29 | ess, err := s.GetEffectiveSecuritySettings()
30 | if err != nil {
31 | return nil, err
32 | }
33 | mss.SecurityType = s.SecurityType
34 | mss.SecuritySettings = ess
35 | }
36 |
37 | return mss, nil
38 | }
39 |
--------------------------------------------------------------------------------
/common/strmatcher/matchers.go:
--------------------------------------------------------------------------------
1 | package strmatcher
2 |
3 | import (
4 | "regexp"
5 | "strings"
6 | )
7 |
8 | type fullMatcher string
9 |
10 | func (m fullMatcher) Match(s string) bool {
11 | return string(m) == s
12 | }
13 |
14 | func (m fullMatcher) String() string {
15 | return "full:" + string(m)
16 | }
17 |
18 | type substrMatcher string
19 |
20 | func (m substrMatcher) Match(s string) bool {
21 | return strings.Contains(s, string(m))
22 | }
23 |
24 | func (m substrMatcher) String() string {
25 | return "keyword:" + string(m)
26 | }
27 |
28 | type domainMatcher string
29 |
30 | func (m domainMatcher) Match(s string) bool {
31 | pattern := string(m)
32 | if !strings.HasSuffix(s, pattern) {
33 | return false
34 | }
35 | return len(s) == len(pattern) || s[len(s)-len(pattern)-1] == '.'
36 | }
37 |
38 | func (m domainMatcher) String() string {
39 | return "domain:" + string(m)
40 | }
41 |
42 | type regexMatcher struct {
43 | pattern *regexp.Regexp
44 | }
45 |
46 | func (m *regexMatcher) Match(s string) bool {
47 | return m.pattern.MatchString(s)
48 | }
49 |
50 | func (m *regexMatcher) String() string {
51 | return "regexp:" + m.pattern.String()
52 | }
53 |
--------------------------------------------------------------------------------
/transport/internet/udp/hub_freebsd.go:
--------------------------------------------------------------------------------
1 | //go:build freebsd
2 | // +build freebsd
3 |
4 | package udp
5 |
6 | import (
7 | "bytes"
8 | "encoding/gob"
9 | "io"
10 |
11 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/net"
12 | "github.com/Shadowsocks-NET/v2ray-go/v4/transport/internet"
13 | )
14 |
15 | // RetrieveOriginalDest from stored laddr, caddr
16 | func RetrieveOriginalDest(oob []byte) net.Destination {
17 | dec := gob.NewDecoder(bytes.NewBuffer(oob))
18 | var la, ra net.UDPAddr
19 | dec.Decode(&la)
20 | dec.Decode(&ra)
21 | ip, port, err := internet.OriginalDst(&la, &ra)
22 | if err != nil {
23 | return net.Destination{}
24 | }
25 | return net.UDPDestination(net.IPAddress(ip), net.Port(port))
26 | }
27 |
28 | // ReadUDPMsg stores laddr, caddr for later use
29 | func ReadUDPMsg(conn *net.UDPConn, payload []byte, oob []byte) (int, int, int, *net.UDPAddr, error) {
30 | nBytes, addr, err := conn.ReadFromUDP(payload)
31 | var buf bytes.Buffer
32 | enc := gob.NewEncoder(&buf)
33 | enc.Encode(conn.LocalAddr().(*net.UDPAddr))
34 | enc.Encode(addr)
35 | var reader io.Reader = &buf
36 | noob, _ := reader.Read(oob)
37 | return nBytes, noob, 0, addr, err
38 | }
39 |
--------------------------------------------------------------------------------
/main/confloader/confloader.go:
--------------------------------------------------------------------------------
1 | package confloader
2 |
3 | //go:generate go run github.com/Shadowsocks-NET/v2ray-go/v4/common/errors/errorgen
4 |
5 | import (
6 | "io"
7 | "os"
8 | )
9 |
10 | type (
11 | configFileLoader func(string) (io.Reader, error)
12 | extconfigLoader func([]string, io.Reader) (io.Reader, error)
13 | )
14 |
15 | var (
16 | EffectiveConfigFileLoader configFileLoader
17 | EffectiveExtConfigLoader extconfigLoader
18 | )
19 |
20 | // LoadConfig reads from a path/url/stdin
21 | // actual work is in external module
22 | func LoadConfig(file string) (io.Reader, error) {
23 | if EffectiveConfigFileLoader == nil {
24 | newError("external config module not loaded, reading from stdin").AtInfo().WriteToLog()
25 | return os.Stdin, nil
26 | }
27 | return EffectiveConfigFileLoader(file)
28 | }
29 |
30 | // LoadExtConfig calls v2ctl to handle multiple config
31 | // the actual work also in external module
32 | func LoadExtConfig(files []string, reader io.Reader) (io.Reader, error) {
33 | if EffectiveExtConfigLoader == nil {
34 | return nil, newError("external config module not loaded").AtError()
35 | }
36 |
37 | return EffectiveExtConfigLoader(files, reader)
38 | }
39 |
--------------------------------------------------------------------------------
/mocks.go:
--------------------------------------------------------------------------------
1 | package core
2 |
3 | //go:generate env GOBIN=$PWD go install -v github.com/golang/mock/mockgen@latest
4 | //go:generate ./mockgen -package mocks -destination testing/mocks/io.go -mock_names Reader=Reader,Writer=Writer io Reader,Writer
5 | //go:generate ./mockgen -package mocks -destination testing/mocks/log.go -mock_names Handler=LogHandler github.com/Shadowsocks-NET/v2ray-go/v4/common/log Handler
6 | //go:generate ./mockgen -package mocks -destination testing/mocks/mux.go -mock_names ClientWorkerFactory=MuxClientWorkerFactory github.com/Shadowsocks-NET/v2ray-go/v4/common/mux ClientWorkerFactory
7 | //go:generate ./mockgen -package mocks -destination testing/mocks/dns.go -mock_names Client=DNSClient github.com/Shadowsocks-NET/v2ray-go/v4/features/dns Client
8 | //go:generate ./mockgen -package mocks -destination testing/mocks/outbound.go -mock_names Manager=OutboundManager,HandlerSelector=OutboundHandlerSelector github.com/Shadowsocks-NET/v2ray-go/v4/features/outbound Manager,HandlerSelector
9 | //go:generate ./mockgen -package mocks -destination testing/mocks/proxy.go -mock_names Inbound=ProxyInbound,Outbound=ProxyOutbound github.com/Shadowsocks-NET/v2ray-go/v4/proxy Inbound,Outbound
10 |
--------------------------------------------------------------------------------
/app/log/command/command_test.go:
--------------------------------------------------------------------------------
1 | package command_test
2 |
3 | import (
4 | "context"
5 | "testing"
6 |
7 | core "github.com/Shadowsocks-NET/v2ray-go/v4"
8 | "github.com/Shadowsocks-NET/v2ray-go/v4/app/dispatcher"
9 | "github.com/Shadowsocks-NET/v2ray-go/v4/app/log"
10 | . "github.com/Shadowsocks-NET/v2ray-go/v4/app/log/command"
11 | "github.com/Shadowsocks-NET/v2ray-go/v4/app/proxyman"
12 | _ "github.com/Shadowsocks-NET/v2ray-go/v4/app/proxyman/inbound"
13 | _ "github.com/Shadowsocks-NET/v2ray-go/v4/app/proxyman/outbound"
14 | "github.com/Shadowsocks-NET/v2ray-go/v4/common"
15 | "github.com/Shadowsocks-NET/v2ray-go/v4/common/serial"
16 | )
17 |
18 | func TestLoggerRestart(t *testing.T) {
19 | v, err := core.New(&core.Config{
20 | App: []*serial.TypedMessage{
21 | serial.ToTypedMessage(&log.Config{}),
22 | serial.ToTypedMessage(&dispatcher.Config{}),
23 | serial.ToTypedMessage(&proxyman.InboundConfig{}),
24 | serial.ToTypedMessage(&proxyman.OutboundConfig{}),
25 | },
26 | })
27 | common.Must(err)
28 | common.Must(v.Start())
29 |
30 | server := &LoggerServer{
31 | V: v,
32 | }
33 | common.Must2(server.RestartLogger(context.Background(), &RestartLoggerRequest{}))
34 | }
35 |
--------------------------------------------------------------------------------