├── .dev └── protoc │ ├── linux │ └── protoc │ ├── macos │ └── protoc │ └── windows │ └── protoc.exe ├── .github ├── CODE_OF_CONDUCT.md ├── ISSUE_TEMPLATE.md ├── ISSUE_TEMPLATE │ ├── bug_cn.md │ ├── bug_en.md │ └── other_en.md ├── dependabot.yml ├── linters │ └── .golangci.yml ├── pull_request_template.md └── workflows │ ├── codeql-analysis.yml │ ├── coverage.yml │ ├── linter.yml │ ├── sign.yml │ ├── stale.yml │ ├── test.yml │ └── updateGeofile.yml ├── .gitignore ├── Dockerfile ├── LICENSE ├── README.md ├── SECURITY.md ├── WORKSPACE ├── annotations.go ├── app ├── app.go ├── commander │ ├── commander.go │ ├── config.pb.go │ ├── config.proto │ ├── errors.generated.go │ ├── outbound.go │ └── service.go ├── dispatcher │ ├── config.pb.go │ ├── config.proto │ ├── default.go │ ├── dispatcher.go │ ├── errors.generated.go │ ├── sniffer.go │ ├── stats.go │ └── stats_test.go ├── dns │ ├── config.pb.go │ ├── config.proto │ ├── dns.go │ ├── dnscommon.go │ ├── dnscommon_test.go │ ├── dohdns.go │ ├── errors.generated.go │ ├── hosts.go │ ├── hosts_test.go │ ├── nameserver.go │ ├── nameserver_test.go │ ├── server.go │ ├── server_test.go │ └── udpns.go ├── log │ ├── command │ │ ├── command.go │ │ ├── command_test.go │ │ ├── config.pb.go │ │ ├── config.proto │ │ ├── config_grpc.pb.go │ │ └── errors.generated.go │ ├── config.pb.go │ ├── config.proto │ ├── errors.generated.go │ ├── log.go │ ├── log_creator.go │ └── log_test.go ├── policy │ ├── config.go │ ├── config.pb.go │ ├── config.proto │ ├── errors.generated.go │ ├── manager.go │ ├── manager_test.go │ └── policy.go ├── proxyman │ ├── command │ │ ├── command.go │ │ ├── command.pb.go │ │ ├── command.proto │ │ ├── command_grpc.pb.go │ │ ├── doc.go │ │ └── errors.generated.go │ ├── config.go │ ├── config.pb.go │ ├── config.proto │ ├── inbound │ │ ├── always.go │ │ ├── dynamic.go │ │ ├── errors.generated.go │ │ ├── inbound.go │ │ └── worker.go │ ├── outbound │ │ ├── errors.generated.go │ │ ├── handler.go │ │ ├── handler_test.go │ │ └── outbound.go │ └── proxyman.go ├── reverse │ ├── bridge.go │ ├── config.go │ ├── config.pb.go │ ├── config.proto │ ├── errors.generated.go │ ├── portal.go │ ├── portal_test.go │ └── reverse.go ├── router │ ├── balancing.go │ ├── command │ │ ├── command.go │ │ ├── command.pb.go │ │ ├── command.proto │ │ ├── command_grpc.pb.go │ │ ├── command_test.go │ │ ├── config.go │ │ └── errors.generated.go │ ├── condition.go │ ├── condition_geoip.go │ ├── condition_geoip_test.go │ ├── condition_test.go │ ├── config.go │ ├── config.pb.go │ ├── config.proto │ ├── errors.generated.go │ ├── router.go │ └── router_test.go └── stats │ ├── channel.go │ ├── channel_test.go │ ├── command │ ├── command.go │ ├── command.pb.go │ ├── command.proto │ ├── command_grpc.pb.go │ ├── command_test.go │ └── errors.generated.go │ ├── config.pb.go │ ├── config.proto │ ├── counter.go │ ├── counter_test.go │ ├── errors.generated.go │ ├── stats.go │ └── stats_test.go ├── azure-pipelines.yml ├── common ├── antireplay │ └── antireplay.go ├── bitmask │ ├── byte.go │ └── byte_test.go ├── buf │ ├── buf.go │ ├── buffer.go │ ├── buffer_test.go │ ├── copy.go │ ├── copy_test.go │ ├── data │ │ └── test_MultiBufferReadAllToByte.dat │ ├── errors.generated.go │ ├── io.go │ ├── io_test.go │ ├── multi_buffer.go │ ├── multi_buffer_test.go │ ├── reader.go │ ├── reader_test.go │ ├── readv_posix.go │ ├── readv_reader.go │ ├── readv_reader_wasm.go │ ├── readv_test.go │ ├── readv_unix.go │ ├── readv_windows.go │ ├── writer.go │ └── writer_test.go ├── bytespool │ └── pool.go ├── cmdarg │ └── cmdarg.go ├── common.go ├── common_test.go ├── crypto │ ├── aes.go │ ├── auth.go │ ├── auth_test.go │ ├── benchmark_test.go │ ├── chacha20.go │ ├── chacha20_test.go │ ├── chunk.go │ ├── chunk_test.go │ ├── crypto.go │ ├── errors.generated.go │ ├── internal │ │ ├── chacha.go │ │ ├── chacha_core.generated.go │ │ └── chacha_core_gen.go │ └── io.go ├── dice │ ├── dice.go │ └── dice_test.go ├── errors.generated.go ├── errors │ ├── errorgen │ │ └── main.go │ ├── errors.go │ ├── errors_test.go │ └── multi_error.go ├── interfaces.go ├── log │ ├── access.go │ ├── log.go │ ├── log.pb.go │ ├── log.proto │ ├── log_test.go │ ├── logger.go │ └── logger_test.go ├── mux │ ├── client.go │ ├── client_test.go │ ├── errors.generated.go │ ├── frame.go │ ├── frame_test.go │ ├── mux.go │ ├── mux_test.go │ ├── reader.go │ ├── server.go │ ├── session.go │ ├── session_test.go │ └── writer.go ├── net │ ├── address.go │ ├── address.pb.go │ ├── address.proto │ ├── address_test.go │ ├── connection.go │ ├── destination.go │ ├── destination.pb.go │ ├── destination.proto │ ├── destination_test.go │ ├── errors.generated.go │ ├── net.go │ ├── network.go │ ├── network.pb.go │ ├── network.proto │ ├── port.go │ ├── port.pb.go │ ├── port.proto │ ├── port_test.go │ └── system.go ├── peer │ ├── latency.go │ └── peer.go ├── platform │ ├── ctlcmd │ │ ├── attr_other.go │ │ ├── attr_windows.go │ │ ├── ctlcmd.go │ │ └── errors.generated.go │ ├── filesystem │ │ └── file.go │ ├── others.go │ ├── platform.go │ ├── platform_test.go │ └── windows.go ├── protocol │ ├── account.go │ ├── address.go │ ├── address_test.go │ ├── bittorrent │ │ └── bittorrent.go │ ├── context.go │ ├── dns │ │ ├── errors.generated.go │ │ └── io.go │ ├── errors.generated.go │ ├── headers.go │ ├── headers.pb.go │ ├── headers.proto │ ├── http │ │ ├── headers.go │ │ ├── headers_test.go │ │ ├── sniff.go │ │ └── sniff_test.go │ ├── id.go │ ├── id_test.go │ ├── payload.go │ ├── protocol.go │ ├── server_picker.go │ ├── server_picker_test.go │ ├── server_spec.go │ ├── server_spec.pb.go │ ├── server_spec.proto │ ├── server_spec_test.go │ ├── time.go │ ├── time_test.go │ ├── tls │ │ ├── cert │ │ │ ├── .gitignore │ │ │ ├── cert.go │ │ │ ├── cert_test.go │ │ │ ├── errors.generated.go │ │ │ └── privateKey.go │ │ ├── sniff.go │ │ └── sniff_test.go │ ├── udp │ │ ├── packet.go │ │ └── udp.go │ ├── user.go │ ├── user.pb.go │ └── user.proto ├── retry │ ├── errors.generated.go │ ├── retry.go │ └── retry_test.go ├── serial │ ├── serial.go │ ├── serial_test.go │ ├── string.go │ ├── string_test.go │ ├── typed_message.go │ ├── typed_message.pb.go │ ├── typed_message.proto │ └── typed_message_test.go ├── session │ ├── context.go │ └── session.go ├── signal │ ├── done │ │ └── done.go │ ├── notifier.go │ ├── notifier_test.go │ ├── pubsub │ │ ├── pubsub.go │ │ └── pubsub_test.go │ ├── semaphore │ │ └── semaphore.go │ ├── timer.go │ └── timer_test.go ├── stack │ └── bytes.go ├── strmatcher │ ├── benchmark_test.go │ ├── domain_matcher.go │ ├── domain_matcher_test.go │ ├── full_matcher.go │ ├── full_matcher_test.go │ ├── matchers.go │ ├── matchers_test.go │ ├── strmatcher.go │ └── strmatcher_test.go ├── task │ ├── common.go │ ├── periodic.go │ ├── periodic_test.go │ ├── task.go │ └── task_test.go ├── type.go ├── type_test.go └── uuid │ ├── uuid.go │ └── uuid_test.go ├── config.go ├── config.pb.go ├── config.proto ├── context.go ├── context_test.go ├── core.go ├── errors.generated.go ├── features ├── dns │ ├── client.go │ └── localdns │ │ └── client.go ├── errors.generated.go ├── feature.go ├── inbound │ └── inbound.go ├── outbound │ └── outbound.go ├── policy │ ├── default.go │ └── policy.go ├── routing │ ├── context.go │ ├── dispatcher.go │ ├── dns │ │ ├── context.go │ │ └── errors.generated.go │ ├── router.go │ └── session │ │ └── context.go └── stats │ ├── errors.generated.go │ └── stats.go ├── functions.go ├── functions_test.go ├── go.mod ├── go.sum ├── infra ├── bazel │ ├── BUILD │ ├── build.bzl │ ├── matrix.bzl │ └── zip.bzl ├── conf │ ├── api.go │ ├── blackhole.go │ ├── blackhole_test.go │ ├── buildable.go │ ├── command │ │ ├── command.go │ │ └── errors.generated.go │ ├── common.go │ ├── common_test.go │ ├── conf.go │ ├── dns.go │ ├── dns_proxy.go │ ├── dns_proxy_test.go │ ├── dns_test.go │ ├── dokodemo.go │ ├── dokodemo_test.go │ ├── errors.generated.go │ ├── freedom.go │ ├── freedom_test.go │ ├── general_test.go │ ├── http.go │ ├── http_test.go │ ├── json │ │ ├── reader.go │ │ └── reader_test.go │ ├── loader.go │ ├── log.go │ ├── mtproto.go │ ├── mtproto_test.go │ ├── policy.go │ ├── policy_test.go │ ├── reverse.go │ ├── reverse_test.go │ ├── router.go │ ├── router_test.go │ ├── serial │ │ ├── errors.generated.go │ │ ├── loader.go │ │ ├── loader_test.go │ │ └── serial.go │ ├── shadowsocks.go │ ├── shadowsocks_test.go │ ├── socks.go │ ├── socks_test.go │ ├── transport.go │ ├── transport_authenticators.go │ ├── transport_internet.go │ ├── transport_test.go │ ├── trojan.go │ ├── v2ray.go │ ├── v2ray_test.go │ ├── vless.go │ ├── vless_test.go │ ├── vmess.go │ └── vmess_test.go ├── control │ ├── api.go │ ├── cert.go │ ├── command.go │ ├── config.go │ ├── control.go │ ├── errors.generated.go │ ├── fetch.go │ ├── love.go │ ├── main │ │ ├── BUILD │ │ ├── main.go │ │ └── targets.bzl │ ├── tlsping.go │ ├── uuid.go │ └── verify.go └── vprotogen │ └── main.go ├── main ├── BUILD ├── confloader │ ├── confloader.go │ ├── errors.generated.go │ └── external │ │ ├── errors.generated.go │ │ └── external.go ├── distro │ ├── all │ │ └── all.go │ └── debug │ │ └── debug.go ├── errors.generated.go ├── json │ ├── config_json.go │ └── errors.generated.go ├── jsonem │ ├── errors.generated.go │ └── jsonem.go ├── main.go ├── main_test.go └── targets.bzl ├── mocks.go ├── proto.go ├── proxy ├── blackhole │ ├── blackhole.go │ ├── blackhole_test.go │ ├── config.go │ ├── config.pb.go │ ├── config.proto │ ├── config_test.go │ └── errors.generated.go ├── dns │ ├── config.pb.go │ ├── config.proto │ ├── dns.go │ ├── dns_test.go │ └── errors.generated.go ├── dokodemo │ ├── config.go │ ├── config.pb.go │ ├── config.proto │ ├── dokodemo.go │ └── errors.generated.go ├── freedom │ ├── config.go │ ├── config.pb.go │ ├── config.proto │ ├── errors.generated.go │ └── freedom.go ├── http │ ├── client.go │ ├── config.go │ ├── config.pb.go │ ├── config.proto │ ├── errors.generated.go │ ├── http.go │ └── server.go ├── mtproto │ ├── auth.go │ ├── auth_test.go │ ├── client.go │ ├── config.go │ ├── config.pb.go │ ├── config.proto │ ├── errors.generated.go │ ├── mtproto.go │ └── server.go ├── proxy.go ├── shadowsocks │ ├── client.go │ ├── config.go │ ├── config.pb.go │ ├── config.proto │ ├── config_test.go │ ├── errors.generated.go │ ├── protocol.go │ ├── protocol_test.go │ ├── server.go │ └── shadowsocks.go ├── socks │ ├── client.go │ ├── config.go │ ├── config.pb.go │ ├── config.proto │ ├── errors.generated.go │ ├── protocol.go │ ├── protocol_test.go │ ├── server.go │ └── socks.go ├── trojan │ ├── client.go │ ├── config.go │ ├── config.pb.go │ ├── config.proto │ ├── errors.generated.go │ ├── protocol.go │ ├── protocol_test.go │ ├── server.go │ ├── trojan.go │ └── validator.go ├── vless │ ├── account.go │ ├── account.pb.go │ ├── account.proto │ ├── encoding │ │ ├── addons.go │ │ ├── addons.pb.go │ │ ├── addons.proto │ │ ├── encoding.go │ │ ├── encoding_test.go │ │ └── errors.generated.go │ ├── errors.generated.go │ ├── inbound │ │ ├── config.go │ │ ├── config.pb.go │ │ ├── config.proto │ │ ├── errors.generated.go │ │ └── inbound.go │ ├── outbound │ │ ├── config.go │ │ ├── config.pb.go │ │ ├── config.proto │ │ ├── errors.generated.go │ │ └── outbound.go │ ├── validator.go │ └── vless.go └── vmess │ ├── account.go │ ├── account.pb.go │ ├── account.proto │ ├── aead │ ├── authid.go │ ├── authid_test.go │ ├── consts.go │ ├── encrypt.go │ ├── encrypt_test.go │ └── kdf.go │ ├── encoding │ ├── auth.go │ ├── auth_test.go │ ├── client.go │ ├── commands.go │ ├── commands_test.go │ ├── encoding.go │ ├── encoding_test.go │ ├── errors.generated.go │ └── server.go │ ├── errors.generated.go │ ├── inbound │ ├── config.go │ ├── config.pb.go │ ├── config.proto │ ├── errors.generated.go │ └── inbound.go │ ├── outbound │ ├── command.go │ ├── config.go │ ├── config.pb.go │ ├── config.proto │ ├── errors.generated.go │ └── outbound.go │ ├── validator.go │ ├── validator_test.go │ ├── vmess.go │ └── vmessCtxInterface.go ├── release ├── BUILD ├── bleedingrelease.sh ├── config │ ├── config.json │ ├── geoip.dat │ ├── geosite.dat │ ├── systemd │ │ └── system │ │ │ ├── v2ray.service │ │ │ └── v2ray@.service │ ├── vpoint_socks_vmess.json │ └── vpoint_vmess_freedom.json ├── install-release.sh ├── mapping.bzl ├── mutilate │ └── removeVSign.sh ├── requestsign.sh ├── requestsign_github.sh ├── tagrelease.sh └── user-package.sh ├── testing ├── coverage │ ├── coverall │ └── coverall2 ├── mocks │ ├── dns.go │ ├── io.go │ ├── log.go │ ├── mux.go │ ├── outbound.go │ └── proxy.go ├── scenarios │ ├── command_test.go │ ├── common.go │ ├── common_coverage.go │ ├── common_regular.go │ ├── dns_test.go │ ├── dokodemo_test.go │ ├── feature_test.go │ ├── http_test.go │ ├── policy_test.go │ ├── reverse_test.go │ ├── shadowsocks_test.go │ ├── socks_test.go │ ├── tls_test.go │ ├── transport_test.go │ └── vmess_test.go └── servers │ ├── http │ └── http.go │ ├── tcp │ ├── port.go │ └── tcp.go │ └── udp │ ├── port.go │ └── udp.go ├── transport ├── config.go ├── config.pb.go ├── config.proto ├── internet │ ├── config.go │ ├── config.pb.go │ ├── config.proto │ ├── connection.go │ ├── dialer.go │ ├── dialer_test.go │ ├── domainsocket │ │ ├── config.go │ │ ├── config.pb.go │ │ ├── config.proto │ │ ├── dial.go │ │ ├── errgen.go │ │ ├── errors.generated.go │ │ ├── listener.go │ │ └── listener_test.go │ ├── errors.generated.go │ ├── header.go │ ├── header_test.go │ ├── headers │ │ ├── http │ │ │ ├── config.go │ │ │ ├── config.pb.go │ │ │ ├── config.proto │ │ │ ├── errors.generated.go │ │ │ ├── http.go │ │ │ ├── http_test.go │ │ │ ├── linkedreadRequest.go │ │ │ └── resp.go │ │ ├── noop │ │ │ ├── config.pb.go │ │ │ ├── config.proto │ │ │ └── noop.go │ │ ├── srtp │ │ │ ├── config.pb.go │ │ │ ├── config.proto │ │ │ ├── srtp.go │ │ │ └── srtp_test.go │ │ ├── tls │ │ │ ├── config.pb.go │ │ │ ├── config.proto │ │ │ ├── dtls.go │ │ │ └── dtls_test.go │ │ ├── utp │ │ │ ├── config.pb.go │ │ │ ├── config.proto │ │ │ ├── utp.go │ │ │ └── utp_test.go │ │ ├── wechat │ │ │ ├── config.pb.go │ │ │ ├── config.proto │ │ │ ├── wechat.go │ │ │ └── wechat_test.go │ │ └── wireguard │ │ │ ├── config.pb.go │ │ │ ├── config.proto │ │ │ └── wireguard.go │ ├── http │ │ ├── config.go │ │ ├── config.pb.go │ │ ├── config.proto │ │ ├── dialer.go │ │ ├── errors.generated.go │ │ ├── http.go │ │ ├── http_test.go │ │ └── hub.go │ ├── internet.go │ ├── kcp │ │ ├── config.go │ │ ├── config.pb.go │ │ ├── config.proto │ │ ├── connection.go │ │ ├── connection_test.go │ │ ├── crypt.go │ │ ├── crypt_test.go │ │ ├── cryptreal.go │ │ ├── dialer.go │ │ ├── errors.generated.go │ │ ├── io.go │ │ ├── io_test.go │ │ ├── kcp.go │ │ ├── kcp_test.go │ │ ├── listener.go │ │ ├── output.go │ │ ├── receiving.go │ │ ├── segment.go │ │ ├── segment_test.go │ │ ├── sending.go │ │ ├── xor.go │ │ ├── xor_amd64.go │ │ └── xor_amd64.s │ ├── memory_settings.go │ ├── quic │ │ ├── config.go │ │ ├── config.pb.go │ │ ├── config.proto │ │ ├── conn.go │ │ ├── dialer.go │ │ ├── errors.generated.go │ │ ├── hub.go │ │ ├── pool.go │ │ ├── quic.go │ │ └── quic_test.go │ ├── sockopt.go │ ├── sockopt_darwin.go │ ├── sockopt_freebsd.go │ ├── sockopt_linux.go │ ├── sockopt_linux_test.go │ ├── sockopt_other.go │ ├── sockopt_test.go │ ├── sockopt_windows.go │ ├── system_dialer.go │ ├── system_listener.go │ ├── system_listener_test.go │ ├── tcp │ │ ├── config.go │ │ ├── config.pb.go │ │ ├── config.proto │ │ ├── dialer.go │ │ ├── errors.generated.go │ │ ├── hub.go │ │ ├── sockopt_freebsd.go │ │ ├── sockopt_linux.go │ │ ├── sockopt_linux_test.go │ │ ├── sockopt_other.go │ │ └── tcp.go │ ├── tcp_hub.go │ ├── tls │ │ ├── config.go │ │ ├── config.pb.go │ │ ├── config.proto │ │ ├── config_other.go │ │ ├── config_test.go │ │ ├── config_windows.go │ │ ├── errors.generated.go │ │ └── tls.go │ ├── udp │ │ ├── config.go │ │ ├── config.pb.go │ │ ├── config.proto │ │ ├── dialer.go │ │ ├── dispatcher.go │ │ ├── dispatcher_test.go │ │ ├── errors.generated.go │ │ ├── hub.go │ │ ├── hub_freebsd.go │ │ ├── hub_linux.go │ │ ├── hub_other.go │ │ └── udp.go │ ├── websocket │ │ ├── config.go │ │ ├── config.pb.go │ │ ├── config.proto │ │ ├── connection.go │ │ ├── dialer.go │ │ ├── errors.generated.go │ │ ├── hub.go │ │ ├── ws.go │ │ └── ws_test.go │ └── xtls │ │ ├── config.go │ │ ├── config.pb.go │ │ ├── config.proto │ │ ├── config_other.go │ │ ├── config_test.go │ │ ├── config_windows.go │ │ ├── errors.generated.go │ │ └── xtls.go ├── link.go └── pipe │ ├── impl.go │ ├── pipe.go │ ├── pipe_test.go │ ├── reader.go │ └── writer.go ├── v2ray.go └── v2ray_test.go /.dev/protoc/linux/protoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/v2ray/v2ray-core/d80440f3d57b45c829dbf513306f7adf9a0f3f76/.dev/protoc/linux/protoc -------------------------------------------------------------------------------- /.dev/protoc/macos/protoc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/v2ray/v2ray-core/d80440f3d57b45c829dbf513306f7adf9a0f3f76/.dev/protoc/macos/protoc -------------------------------------------------------------------------------- /.dev/protoc/windows/protoc.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/v2ray/v2ray-core/d80440f3d57b45c829dbf513306f7adf9a0f3f76/.dev/protoc/windows/protoc.exe -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 如果你遇到的问题不是 V2Ray 的 bug,比如你不清楚要如何配置,请使用[Discussion](https://github.com/v2fly/discussion/issues)进行讨论。 2 | 3 | 此 Issue 会被立即关闭。 4 | 5 | If you are not sure if your question is truely a bug in V2Ray, please discuss it [here](https://github.com/v2fly/discussion/issues) first. 6 | 7 | This issue will be closed immediately. 8 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/other_en.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Other 3 | about: "其它问题请使用 https://github.com/v2fly/discussion/issues 进行讨论 / Please discuss other issues at https://github.com/v2fly/discussion/issues" 4 | --- 5 | 6 | 如果你遇到的问题不是 V2Ray 的 bug,比如你不清楚要如何配置,请使用[Discussion](https://github.com/v2fly/discussion/issues)进行讨论。 7 | 8 | 此 Issue 会被立即关闭。 9 | 10 | If you are not sure if your question is truely a bug in V2Ray, please discuss it [here](https://github.com/v2fly/discussion/issues) first. 11 | 12 | This issue will be closed immediately. 13 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.github/linters/.golangci.yml: -------------------------------------------------------------------------------- 1 | run: 2 | timeout: 5m 3 | skip-files: 4 | - generated.* 5 | 6 | issues: 7 | new: true 8 | 9 | linters: 10 | enable: 11 | - bodyclose 12 | - depguard 13 | - gocritic 14 | - gofmt 15 | - goimports 16 | - golint 17 | - goprintffuncname 18 | - gosimple 19 | - govet 20 | - ineffassign 21 | - misspell 22 | - nakedret 23 | - noctx 24 | - nolintlint 25 | - rowserrcheck 26 | - scopelint 27 | - staticcheck 28 | - structcheck 29 | - stylecheck 30 | - typecheck 31 | - unconvert 32 | - unparam 33 | - varcheck 34 | - whitespace 35 | disable: 36 | - deadcode 37 | - errcheck 38 | - unused 39 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | Please Move to https://github.com/v2fly/v2ray-core/pulls 2 | -------------------------------------------------------------------------------- /.github/workflows/coverage.yml: -------------------------------------------------------------------------------- 1 | name: Coverage 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | paths: 7 | - "**/*.go" 8 | 9 | jobs: 10 | coverage: 11 | if: github.repository != 'v2ray/v2ray-core' 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Set up Go 1.x 15 | uses: actions/setup-go@v2 16 | with: 17 | go-version: ^1.15 18 | 19 | - name: Checkout codebase 20 | uses: actions/checkout@v2 21 | 22 | - name: Cache go module 23 | uses: actions/cache@v2 24 | id: cache-gomodules 25 | with: 26 | path: ~/go/pkg/mod 27 | key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} 28 | restore-keys: | 29 | ${{ runner.os }}-go- 30 | 31 | - name: Get dependencies 32 | if: steps.cache-gomodules.outputs.cache-hit != 'true' 33 | run: | 34 | go get -v -t -d ./... 35 | 36 | - name: Run coverage 37 | run: ./testing/coverage/coverall2 38 | 39 | - name: Upload coverage to Codecov 40 | uses: codecov/codecov-action@v1 41 | with: 42 | file: ./coverage.txt 43 | fail_ci_if_error: true 44 | -------------------------------------------------------------------------------- /.github/workflows/linter.yml: -------------------------------------------------------------------------------- 1 | name: Linter 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | paths: 7 | - "**/*.go" 8 | pull_request: 9 | branches: [master] 10 | types: [opened, synchronize, reopened] 11 | paths: 12 | - "**/*.go" 13 | 14 | jobs: 15 | lint: 16 | if: github.repository != 'v2ray/v2ray-core' 17 | runs-on: ubuntu-latest 18 | steps: 19 | - name: Set up Go 1.x 20 | uses: actions/setup-go@v2 21 | with: 22 | go-version: ^1.15 23 | 24 | - name: Checkout codebase 25 | uses: actions/checkout@v2 26 | 27 | - name: golangci-lint 28 | uses: golangci/golangci-lint-action@v2 29 | with: 30 | version: v1.31 31 | args: --config=.github/linters/.golangci.yml 32 | only-new-issues: true 33 | -------------------------------------------------------------------------------- /.github/workflows/sign.yml: -------------------------------------------------------------------------------- 1 | name: Sign 2 | 3 | on: 4 | release: 5 | types: [released] 6 | 7 | jobs: 8 | sign: 9 | if: github.repository != 'v2ray/v2ray-core' 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout default branch 13 | uses: actions/checkout@v2 14 | 15 | - name: Grant it execution permission 16 | run: | 17 | chmod +x $GITHUB_WORKSPACE/release/requestsign_github.sh 18 | chmod +x $GITHUB_WORKSPACE/release/requestsign.sh 19 | 20 | - name: Invoke release signing 21 | env: 22 | SIGN_SERVICE_PASSWORD: ${{ secrets.SIGN_SERVICE_PASSWORD }} 23 | SIGN_SERIVCE_URL: ${{ secrets.SIGN_SERIVCE_URL }} 24 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 25 | run: $GITHUB_WORKSPACE/release/requestsign_github.sh 26 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | name: Mark stale issues and pull requests 2 | 3 | on: 4 | schedule: 5 | - cron: "30 1 * * *" 6 | 7 | jobs: 8 | stale: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/stale@v3.0.13 12 | with: 13 | repo-token: ${{ secrets.GITHUB_TOKEN }} 14 | stale-issue-message: "This issue is stale because it has been open 120 days with no activity. Remove stale label or comment or this will be closed in 5 days" 15 | stale-pr-message: 'It has been open 120 days with no activity. Remove stale label or comment or this will be closed in 5 days' 16 | days-before-stale: 120 17 | days-before-close: 5 18 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | paths: 7 | - "**/*.go" 8 | - "go.mod" 9 | - "go.sum" 10 | pull_request: 11 | branches: [master] 12 | types: [opened, synchronize, reopened] 13 | paths: 14 | - "**/*.go" 15 | - "go.mod" 16 | - "go.sum" 17 | 18 | jobs: 19 | test: 20 | if: github.repository != 'v2ray/v2ray-core' 21 | runs-on: ${{ matrix.os }} 22 | strategy: 23 | matrix: 24 | os: [windows-latest, ubuntu-latest, macos-latest] 25 | steps: 26 | - name: Set up Go 1.x 27 | uses: actions/setup-go@v2 28 | with: 29 | go-version: ^1.15 30 | 31 | - name: Checkout codebase 32 | uses: actions/checkout@v2 33 | 34 | - name: Cache go module 35 | uses: actions/cache@v2 36 | with: 37 | path: ~/go/pkg/mod 38 | key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} 39 | restore-keys: ${{ runner.os }}-go- 40 | 41 | - name: Test 42 | run: go test -timeout 1h -v ./... 43 | -------------------------------------------------------------------------------- /.github/workflows/updateGeofile.yml: -------------------------------------------------------------------------------- 1 | name: Update Geofiles 2 | 3 | on: 4 | schedule: 5 | - cron: "0 0 * * FRI" 6 | 7 | jobs: 8 | update: 9 | if: github.repository == 'v2fly/v2ray-core' 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout codebase 13 | uses: actions/checkout@v2 14 | 15 | - name: Download 16 | run: | 17 | curl -L -o release/config/geoip.dat "https://github.com/v2fly/geoip/raw/release/geoip.dat" 18 | curl -L -o release/config/geosite.dat "https://github.com/v2fly/domain-list-community/raw/release/dlc.dat" 19 | 20 | - name: push 21 | run: | 22 | git config --local user.email "action@github.com" 23 | git config --local user.name "GitHub Action" 24 | git commit -am "update geoip, geosite" 25 | git push -v --progress 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.DS_Store 2 | bazel-* 3 | .idea -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | ############################ 2 | # STEP 1 build executable binary 3 | ############################ 4 | FROM golang:alpine AS builder 5 | 6 | RUN apk update && apk add --no-cache git bash wget curl 7 | WORKDIR /build 8 | RUN git clone --progress https://github.com/v2fly/v2ray-core.git . && \ 9 | bash ./release/user-package.sh nosource noconf codename=$(git describe --abbrev=0 --tags) buildname=docker-fly abpathtgz=/tmp/v2ray.tgz 10 | 11 | ############################ 12 | # STEP 2 build a small image 13 | ############################ 14 | FROM alpine 15 | 16 | LABEL maintainer "V2Fly Community " 17 | COPY --from=builder /tmp/v2ray.tgz /tmp 18 | RUN apk update && apk add ca-certificates && \ 19 | mkdir -p /usr/bin/v2ray && \ 20 | tar xvfz /tmp/v2ray.tgz -C /usr/bin/v2ray 21 | 22 | #ENTRYPOINT ["/usr/bin/v2ray/v2ray"] 23 | ENV PATH /usr/bin/v2ray:$PATH 24 | CMD ["v2ray", "-config=/etc/v2ray/config.json"] 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-2020 V2Fly Community 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /WORKSPACE: -------------------------------------------------------------------------------- 1 | workspace(name = "v2ray_core") 2 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /app/app.go: -------------------------------------------------------------------------------- 1 | // Package app contains feature implementations of V2Ray. The features may be enabled during runtime. 2 | package app 3 | -------------------------------------------------------------------------------- /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 = "v2ray.com/core/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 | -------------------------------------------------------------------------------- /app/commander/errors.generated.go: -------------------------------------------------------------------------------- 1 | package commander 2 | 3 | import "v2ray.com/core/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/service.go: -------------------------------------------------------------------------------- 1 | // +build !confonly 2 | 3 | package commander 4 | 5 | import ( 6 | "google.golang.org/grpc" 7 | ) 8 | 9 | // Service is a Commander service. 10 | type Service interface { 11 | // Register registers the service itself to a gRPC server. 12 | Register(*grpc.Server) 13 | } 14 | -------------------------------------------------------------------------------- /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 = "v2ray.com/core/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 | -------------------------------------------------------------------------------- /app/dispatcher/dispatcher.go: -------------------------------------------------------------------------------- 1 | // +build !confonly 2 | 3 | package dispatcher 4 | 5 | //go:generate go run v2ray.com/core/common/errors/errorgen 6 | -------------------------------------------------------------------------------- /app/dispatcher/errors.generated.go: -------------------------------------------------------------------------------- 1 | package dispatcher 2 | 3 | import "v2ray.com/core/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/stats.go: -------------------------------------------------------------------------------- 1 | // +build !confonly 2 | 3 | package dispatcher 4 | 5 | import ( 6 | "v2ray.com/core/common" 7 | "v2ray.com/core/common/buf" 8 | "v2ray.com/core/features/stats" 9 | ) 10 | 11 | type SizeStatWriter struct { 12 | Counter stats.Counter 13 | Writer buf.Writer 14 | } 15 | 16 | func (w *SizeStatWriter) WriteMultiBuffer(mb buf.MultiBuffer) error { 17 | w.Counter.Add(int64(mb.Len())) 18 | return w.Writer.WriteMultiBuffer(mb) 19 | } 20 | 21 | func (w *SizeStatWriter) Close() error { 22 | return common.Close(w.Writer) 23 | } 24 | 25 | func (w *SizeStatWriter) Interrupt() { 26 | common.Interrupt(w.Writer) 27 | } 28 | -------------------------------------------------------------------------------- /app/dispatcher/stats_test.go: -------------------------------------------------------------------------------- 1 | package dispatcher_test 2 | 3 | import ( 4 | "testing" 5 | 6 | . "v2ray.com/core/app/dispatcher" 7 | "v2ray.com/core/common" 8 | "v2ray.com/core/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 | -------------------------------------------------------------------------------- /app/dns/dns.go: -------------------------------------------------------------------------------- 1 | // Package dns is an implementation of core.DNS feature. 2 | package dns 3 | 4 | //go:generate go run v2ray.com/core/common/errors/errorgen 5 | -------------------------------------------------------------------------------- /app/dns/errors.generated.go: -------------------------------------------------------------------------------- 1 | package dns 2 | 3 | import "v2ray.com/core/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/nameserver_test.go: -------------------------------------------------------------------------------- 1 | package dns_test 2 | 3 | import ( 4 | "context" 5 | "testing" 6 | "time" 7 | 8 | . "v2ray.com/core/app/dns" 9 | "v2ray.com/core/common" 10 | ) 11 | 12 | func TestLocalNameServer(t *testing.T) { 13 | s := NewLocalNameServer() 14 | ctx, cancel := context.WithTimeout(context.Background(), time.Second*2) 15 | ips, err := s.QueryIP(ctx, "google.com", IPOption{ 16 | IPv4Enable: true, 17 | IPv6Enable: true, 18 | }) 19 | cancel() 20 | common.Must(err) 21 | if len(ips) == 0 { 22 | t.Error("expect some ips, but got 0") 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/log/command/command_test.go: -------------------------------------------------------------------------------- 1 | package command_test 2 | 3 | import ( 4 | "context" 5 | "testing" 6 | 7 | "v2ray.com/core" 8 | "v2ray.com/core/app/dispatcher" 9 | "v2ray.com/core/app/log" 10 | . "v2ray.com/core/app/log/command" 11 | "v2ray.com/core/app/proxyman" 12 | _ "v2ray.com/core/app/proxyman/inbound" 13 | _ "v2ray.com/core/app/proxyman/outbound" 14 | "v2ray.com/core/common" 15 | "v2ray.com/core/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 | -------------------------------------------------------------------------------- /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 = "v2ray.com/core/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 | -------------------------------------------------------------------------------- /app/log/command/errors.generated.go: -------------------------------------------------------------------------------- 1 | package command 2 | 3 | import "v2ray.com/core/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/config.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package v2ray.core.app.log; 4 | option csharp_namespace = "V2Ray.Core.App.Log"; 5 | option go_package = "v2ray.com/core/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 | -------------------------------------------------------------------------------- /app/log/errors.generated.go: -------------------------------------------------------------------------------- 1 | package log 2 | 3 | import "v2ray.com/core/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 "v2ray.com/core/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/manager_test.go: -------------------------------------------------------------------------------- 1 | package policy_test 2 | 3 | import ( 4 | "context" 5 | "testing" 6 | "time" 7 | 8 | . "v2ray.com/core/app/policy" 9 | "v2ray.com/core/common" 10 | "v2ray.com/core/features/policy" 11 | ) 12 | 13 | func TestPolicy(t *testing.T) { 14 | manager, err := New(context.Background(), &Config{ 15 | Level: map[uint32]*Policy{ 16 | 0: { 17 | Timeout: &Policy_Timeout{ 18 | Handshake: &Second{ 19 | Value: 2, 20 | }, 21 | }, 22 | }, 23 | }, 24 | }) 25 | common.Must(err) 26 | 27 | pDefault := policy.SessionDefault() 28 | 29 | { 30 | p := manager.ForLevel(0) 31 | if p.Timeouts.Handshake != 2*time.Second { 32 | t.Error("expect 2 sec timeout, but got ", p.Timeouts.Handshake) 33 | } 34 | if p.Timeouts.ConnectionIdle != pDefault.Timeouts.ConnectionIdle { 35 | t.Error("expect ", pDefault.Timeouts.ConnectionIdle, " sec timeout, but got ", p.Timeouts.ConnectionIdle) 36 | } 37 | } 38 | 39 | { 40 | p := manager.ForLevel(1) 41 | if p.Timeouts.Handshake != pDefault.Timeouts.Handshake { 42 | t.Error("expect ", pDefault.Timeouts.Handshake, " sec timeout, but got ", p.Timeouts.Handshake) 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/policy/policy.go: -------------------------------------------------------------------------------- 1 | // Package policy is an implementation of policy.Manager feature. 2 | package policy 3 | 4 | //go:generate go run v2ray.com/core/common/errors/errorgen 5 | -------------------------------------------------------------------------------- /app/proxyman/command/doc.go: -------------------------------------------------------------------------------- 1 | package command 2 | 3 | //go:generate go run v2ray.com/core/common/errors/errorgen 4 | -------------------------------------------------------------------------------- /app/proxyman/command/errors.generated.go: -------------------------------------------------------------------------------- 1 | package command 2 | 3 | import "v2ray.com/core/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/config.go: -------------------------------------------------------------------------------- 1 | package proxyman 2 | 3 | func (s *AllocationStrategy) GetConcurrencyValue() uint32 { 4 | if s == nil || s.Concurrency == nil { 5 | return 3 6 | } 7 | return s.Concurrency.Value 8 | } 9 | 10 | func (s *AllocationStrategy) GetRefreshValue() uint32 { 11 | if s == nil || s.Refresh == nil { 12 | return 5 13 | } 14 | return s.Refresh.Value 15 | } 16 | 17 | func (c *ReceiverConfig) GetEffectiveSniffingSettings() *SniffingConfig { 18 | if c.SniffingSettings != nil { 19 | return c.SniffingSettings 20 | } 21 | 22 | if len(c.DomainOverride) > 0 { 23 | var p []string 24 | for _, kd := range c.DomainOverride { 25 | switch kd { 26 | case KnownProtocols_HTTP: 27 | p = append(p, "http") 28 | case KnownProtocols_TLS: 29 | p = append(p, "tls") 30 | } 31 | } 32 | return &SniffingConfig{ 33 | Enabled: true, 34 | DestinationOverride: p, 35 | } 36 | } 37 | 38 | return nil 39 | } 40 | -------------------------------------------------------------------------------- /app/proxyman/inbound/errors.generated.go: -------------------------------------------------------------------------------- 1 | package inbound 2 | 3 | import "v2ray.com/core/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 "v2ray.com/core/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/proxyman.go: -------------------------------------------------------------------------------- 1 | // Package proxyman defines applications for managing inbound and outbound proxies. 2 | package proxyman 3 | 4 | import ( 5 | "context" 6 | 7 | "v2ray.com/core/common/session" 8 | ) 9 | 10 | // ContextWithSniffingConfig is a wrapper of session.ContextWithContent. 11 | // Deprecated. Use session.ContextWithContent directly. 12 | func ContextWithSniffingConfig(ctx context.Context, c *SniffingConfig) context.Context { 13 | content := session.ContentFromContext(ctx) 14 | if content == nil { 15 | content = new(session.Content) 16 | ctx = session.ContextWithContent(ctx, content) 17 | } 18 | content.SniffingRequest.Enabled = c.Enabled 19 | content.SniffingRequest.OverrideDestinationForProtocol = c.DestinationOverride 20 | return ctx 21 | } 22 | -------------------------------------------------------------------------------- /app/reverse/config.go: -------------------------------------------------------------------------------- 1 | // +build !confonly 2 | 3 | package reverse 4 | 5 | import ( 6 | "crypto/rand" 7 | "io" 8 | 9 | "v2ray.com/core/common/dice" 10 | ) 11 | 12 | func (c *Control) FillInRandom() { 13 | randomLength := dice.Roll(64) 14 | c.Random = make([]byte, randomLength) 15 | io.ReadFull(rand.Reader, c.Random) 16 | } 17 | -------------------------------------------------------------------------------- /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 = "v2ray.com/core/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 | -------------------------------------------------------------------------------- /app/reverse/errors.generated.go: -------------------------------------------------------------------------------- 1 | package reverse 2 | 3 | import "v2ray.com/core/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/portal_test.go: -------------------------------------------------------------------------------- 1 | package reverse_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "v2ray.com/core/app/reverse" 7 | "v2ray.com/core/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 | -------------------------------------------------------------------------------- /app/router/balancing.go: -------------------------------------------------------------------------------- 1 | // +build !confonly 2 | 3 | package router 4 | 5 | import ( 6 | "v2ray.com/core/common/dice" 7 | "v2ray.com/core/features/outbound" 8 | ) 9 | 10 | type BalancingStrategy interface { 11 | PickOutbound([]string) string 12 | } 13 | 14 | type RandomStrategy struct { 15 | } 16 | 17 | func (s *RandomStrategy) PickOutbound(tags []string) string { 18 | n := len(tags) 19 | if n == 0 { 20 | panic("0 tags") 21 | } 22 | 23 | return tags[dice.Roll(n)] 24 | } 25 | 26 | type Balancer struct { 27 | selectors []string 28 | strategy BalancingStrategy 29 | ohm outbound.Manager 30 | } 31 | 32 | func (b *Balancer) PickOutbound() (string, error) { 33 | hs, ok := b.ohm.(outbound.HandlerSelector) 34 | if !ok { 35 | return "", newError("outbound.Manager is not a HandlerSelector") 36 | } 37 | tags := hs.Select(b.selectors) 38 | if len(tags) == 0 { 39 | return "", newError("no available outbounds selected") 40 | } 41 | tag := b.strategy.PickOutbound(tags) 42 | if tag == "" { 43 | return "", newError("balancing strategy returns empty tag") 44 | } 45 | return tag, nil 46 | } 47 | -------------------------------------------------------------------------------- /app/router/command/errors.generated.go: -------------------------------------------------------------------------------- 1 | package command 2 | 3 | import "v2ray.com/core/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 "v2ray.com/core/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 "v2ray.com/core/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/config.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package v2ray.core.app.stats; 4 | option csharp_namespace = "V2Ray.Core.App.Stats"; 5 | option go_package = "v2ray.com/core/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 | -------------------------------------------------------------------------------- /app/stats/counter.go: -------------------------------------------------------------------------------- 1 | // +build !confonly 2 | 3 | package stats 4 | 5 | import "sync/atomic" 6 | 7 | // Counter is an implementation of stats.Counter. 8 | type Counter struct { 9 | value int64 10 | } 11 | 12 | // Value implements stats.Counter. 13 | func (c *Counter) Value() int64 { 14 | return atomic.LoadInt64(&c.value) 15 | } 16 | 17 | // Set implements stats.Counter. 18 | func (c *Counter) Set(newValue int64) int64 { 19 | return atomic.SwapInt64(&c.value, newValue) 20 | } 21 | 22 | // Add implements stats.Counter. 23 | func (c *Counter) Add(delta int64) int64 { 24 | return atomic.AddInt64(&c.value, delta) 25 | } 26 | -------------------------------------------------------------------------------- /app/stats/counter_test.go: -------------------------------------------------------------------------------- 1 | package stats_test 2 | 3 | import ( 4 | "context" 5 | "testing" 6 | 7 | . "v2ray.com/core/app/stats" 8 | "v2ray.com/core/common" 9 | "v2ray.com/core/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 | -------------------------------------------------------------------------------- /app/stats/errors.generated.go: -------------------------------------------------------------------------------- 1 | package stats 2 | 3 | import "v2ray.com/core/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/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/bitmask/byte_test.go: -------------------------------------------------------------------------------- 1 | package bitmask_test 2 | 3 | import ( 4 | "testing" 5 | 6 | . "v2ray.com/core/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 | -------------------------------------------------------------------------------- /common/buf/buf.go: -------------------------------------------------------------------------------- 1 | // Package buf provides a light-weight memory allocation mechanism. 2 | package buf // import "v2ray.com/core/common/buf" 3 | 4 | //go:generate go run v2ray.com/core/common/errors/errorgen 5 | -------------------------------------------------------------------------------- /common/buf/errors.generated.go: -------------------------------------------------------------------------------- 1 | package buf 2 | 3 | import "v2ray.com/core/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_posix.go: -------------------------------------------------------------------------------- 1 | // +build !windows 2 | // +build !wasm 3 | // +build !illumos 4 | 5 | package buf 6 | 7 | import ( 8 | "syscall" 9 | "unsafe" 10 | ) 11 | 12 | type posixReader struct { 13 | iovecs []syscall.Iovec 14 | } 15 | 16 | func (r *posixReader) Init(bs []*Buffer) { 17 | iovecs := r.iovecs 18 | if iovecs == nil { 19 | iovecs = make([]syscall.Iovec, 0, len(bs)) 20 | } 21 | for idx, b := range bs { 22 | iovecs = append(iovecs, syscall.Iovec{ 23 | Base: &(b.v[0]), 24 | }) 25 | iovecs[idx].SetLen(int(Size)) 26 | } 27 | r.iovecs = iovecs 28 | } 29 | 30 | func (r *posixReader) Read(fd uintptr) int32 { 31 | n, _, e := syscall.Syscall(syscall.SYS_READV, fd, uintptr(unsafe.Pointer(&r.iovecs[0])), uintptr(len(r.iovecs))) 32 | if e != 0 { 33 | return -1 34 | } 35 | return int32(n) 36 | } 37 | 38 | func (r *posixReader) Clear() { 39 | for idx := range r.iovecs { 40 | r.iovecs[idx].Base = nil 41 | } 42 | r.iovecs = r.iovecs[:0] 43 | } 44 | 45 | func newMultiReader() multiReader { 46 | return &posixReader{} 47 | } 48 | -------------------------------------------------------------------------------- /common/buf/readv_reader_wasm.go: -------------------------------------------------------------------------------- 1 | // +build wasm 2 | 3 | package buf 4 | 5 | import ( 6 | "io" 7 | "syscall" 8 | ) 9 | 10 | const useReadv = false 11 | 12 | func NewReadVReader(reader io.Reader, rawConn syscall.RawConn) Reader { 13 | panic("not implemented") 14 | } 15 | -------------------------------------------------------------------------------- /common/buf/readv_unix.go: -------------------------------------------------------------------------------- 1 | // +build illumos 2 | 3 | package buf 4 | 5 | import "golang.org/x/sys/unix" 6 | 7 | type unixReader struct { 8 | iovs [][]byte 9 | } 10 | 11 | func (r *unixReader) Init(bs []*Buffer) { 12 | iovs := r.iovs 13 | if iovs == nil { 14 | iovs = make([][]byte, 0, len(bs)) 15 | } 16 | for _, b := range bs { 17 | iovs = append(iovs, b.v) 18 | } 19 | r.iovs = iovs 20 | } 21 | 22 | func (r *unixReader) Read(fd uintptr) int32 { 23 | n, e := unix.Readv(int(fd), r.iovs) 24 | if e != nil { 25 | return -1 26 | } 27 | return int32(n) 28 | } 29 | 30 | func (r *unixReader) Clear() { 31 | r.iovs = r.iovs[:0] 32 | } 33 | 34 | func newMultiReader() multiReader { 35 | return &unixReader{} 36 | } 37 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /common/common_test.go: -------------------------------------------------------------------------------- 1 | package common_test 2 | 3 | import ( 4 | "errors" 5 | "testing" 6 | 7 | . "v2ray.com/core/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 | -------------------------------------------------------------------------------- /common/crypto/chacha20.go: -------------------------------------------------------------------------------- 1 | package crypto 2 | 3 | import ( 4 | "crypto/cipher" 5 | 6 | "v2ray.com/core/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 | -------------------------------------------------------------------------------- /common/crypto/crypto.go: -------------------------------------------------------------------------------- 1 | // Package crypto provides common crypto libraries for V2Ray. 2 | package crypto // import "v2ray.com/core/common/crypto" 3 | 4 | //go:generate go run v2ray.com/core/common/errors/errorgen 5 | -------------------------------------------------------------------------------- /common/crypto/errors.generated.go: -------------------------------------------------------------------------------- 1 | package crypto 2 | 3 | import "v2ray.com/core/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/dice/dice_test.go: -------------------------------------------------------------------------------- 1 | package dice_test 2 | 3 | import ( 4 | "math/rand" 5 | "testing" 6 | 7 | . "v2ray.com/core/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 | -------------------------------------------------------------------------------- /common/errors.generated.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import "v2ray.com/core/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/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 | -------------------------------------------------------------------------------- /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 = "v2ray.com/core/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 | -------------------------------------------------------------------------------- /common/log/log_test.go: -------------------------------------------------------------------------------- 1 | package log_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/google/go-cmp/cmp" 7 | 8 | "v2ray.com/core/common/log" 9 | "v2ray.com/core/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 | -------------------------------------------------------------------------------- /common/log/logger_test.go: -------------------------------------------------------------------------------- 1 | package log_test 2 | 3 | import ( 4 | "io/ioutil" 5 | "os" 6 | "strings" 7 | "testing" 8 | "time" 9 | 10 | "v2ray.com/core/common" 11 | "v2ray.com/core/common/buf" 12 | . "v2ray.com/core/common/log" 13 | ) 14 | 15 | func TestFileLogger(t *testing.T) { 16 | f, err := ioutil.TempFile("", "vtest") 17 | common.Must(err) 18 | path := f.Name() 19 | common.Must(f.Close()) 20 | 21 | creator, err := CreateFileLogWriter(path) 22 | common.Must(err) 23 | 24 | handler := NewLogger(creator) 25 | handler.Handle(&GeneralMessage{Content: "Test Log"}) 26 | time.Sleep(2 * time.Second) 27 | 28 | common.Must(common.Close(handler)) 29 | 30 | f, err = os.Open(path) 31 | common.Must(err) 32 | defer f.Close() // nolint: errcheck 33 | 34 | b, err := buf.ReadAllToBytes(f) 35 | common.Must(err) 36 | if !strings.Contains(string(b), "Test Log") { 37 | t.Fatal("Expect log text contains 'Test Log', but actually: ", string(b)) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /common/mux/errors.generated.go: -------------------------------------------------------------------------------- 1 | package mux 2 | 3 | import "v2ray.com/core/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/frame_test.go: -------------------------------------------------------------------------------- 1 | package mux_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "v2ray.com/core/common" 7 | "v2ray.com/core/common/buf" 8 | "v2ray.com/core/common/mux" 9 | "v2ray.com/core/common/net" 10 | ) 11 | 12 | func BenchmarkFrameWrite(b *testing.B) { 13 | frame := mux.FrameMetadata{ 14 | Target: net.TCPDestination(net.DomainAddress("www.v2ray.com"), 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 | -------------------------------------------------------------------------------- /common/mux/mux.go: -------------------------------------------------------------------------------- 1 | package mux 2 | 3 | //go:generate go run v2ray.com/core/common/errors/errorgen 4 | -------------------------------------------------------------------------------- /common/mux/session_test.go: -------------------------------------------------------------------------------- 1 | package mux_test 2 | 3 | import ( 4 | "testing" 5 | 6 | . "v2ray.com/core/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 | -------------------------------------------------------------------------------- /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 = "v2ray.com/core/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 | -------------------------------------------------------------------------------- /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 = "v2ray.com/core/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/errors.generated.go: -------------------------------------------------------------------------------- 1 | package net 2 | 3 | import "v2ray.com/core/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/net.go: -------------------------------------------------------------------------------- 1 | // Package net is a drop-in replacement to Golang's net package, with some more functionalities. 2 | package net // import "v2ray.com/core/common/net" 3 | 4 | //go:generate go run v2ray.com/core/common/errors/errorgen 5 | -------------------------------------------------------------------------------- /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 | default: 10 | return "unknown" 11 | } 12 | } 13 | 14 | // HasNetwork returns true if the network list has a certain network. 15 | func HasNetwork(list []Network, network Network) bool { 16 | for _, value := range list { 17 | if value == network { 18 | return true 19 | } 20 | } 21 | return false 22 | } 23 | -------------------------------------------------------------------------------- /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 = "v2ray.com/core/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 | } 16 | 17 | // NetworkList is a list of Networks. 18 | message NetworkList { 19 | repeated Network network = 1; 20 | } 21 | -------------------------------------------------------------------------------- /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 = "v2ray.com/core/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 | -------------------------------------------------------------------------------- /common/net/port_test.go: -------------------------------------------------------------------------------- 1 | package net_test 2 | 3 | import ( 4 | "testing" 5 | 6 | . "v2ray.com/core/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 | -------------------------------------------------------------------------------- /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/peer/peer.go: -------------------------------------------------------------------------------- 1 | package peer 2 | -------------------------------------------------------------------------------- /common/platform/ctlcmd/attr_other.go: -------------------------------------------------------------------------------- 1 | // +build !windows 2 | 3 | package ctlcmd 4 | 5 | import "syscall" 6 | 7 | func getSysProcAttr() *syscall.SysProcAttr { 8 | return nil 9 | } 10 | -------------------------------------------------------------------------------- /common/platform/ctlcmd/attr_windows.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | 3 | package ctlcmd 4 | 5 | import "syscall" 6 | 7 | func getSysProcAttr() *syscall.SysProcAttr { 8 | return &syscall.SysProcAttr{ 9 | HideWindow: true, 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /common/platform/ctlcmd/errors.generated.go: -------------------------------------------------------------------------------- 1 | package ctlcmd 2 | 3 | import "v2ray.com/core/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/filesystem/file.go: -------------------------------------------------------------------------------- 1 | package filesystem 2 | 3 | import ( 4 | "io" 5 | "os" 6 | 7 | "v2ray.com/core/common/buf" 8 | "v2ray.com/core/common/platform" 9 | ) 10 | 11 | type FileReaderFunc func(path string) (io.ReadCloser, error) 12 | 13 | var NewFileReader FileReaderFunc = func(path string) (io.ReadCloser, error) { 14 | return os.Open(path) 15 | } 16 | 17 | func ReadFile(path string) ([]byte, error) { 18 | reader, err := NewFileReader(path) 19 | if err != nil { 20 | return nil, err 21 | } 22 | defer reader.Close() 23 | 24 | return buf.ReadAllToBytes(reader) 25 | } 26 | 27 | func ReadAsset(file string) ([]byte, error) { 28 | return ReadFile(platform.GetAssetLocation(file)) 29 | } 30 | 31 | func CopyFile(dst string, src string) error { 32 | bytes, err := ReadFile(src) 33 | if err != nil { 34 | return err 35 | } 36 | f, err := os.OpenFile(dst, os.O_CREATE|os.O_WRONLY, 0644) 37 | if err != nil { 38 | return err 39 | } 40 | defer f.Close() 41 | 42 | _, err = f.Write(bytes) 43 | return err 44 | } 45 | -------------------------------------------------------------------------------- /common/platform/others.go: -------------------------------------------------------------------------------- 1 | // +build !windows 2 | 3 | package platform 4 | 5 | import ( 6 | "os" 7 | "path/filepath" 8 | ) 9 | 10 | func ExpandEnv(s string) string { 11 | return os.ExpandEnv(s) 12 | } 13 | 14 | func LineSeparator() string { 15 | return "\n" 16 | } 17 | 18 | func GetToolLocation(file string) string { 19 | const name = "v2ray.location.tool" 20 | toolPath := EnvFlag{Name: name, AltName: NormalizeEnvName(name)}.GetValue(getExecutableDir) 21 | return filepath.Join(toolPath, file) 22 | } 23 | 24 | // GetAssetLocation search for `file` in certain locations 25 | func GetAssetLocation(file string) string { 26 | const name = "v2ray.location.asset" 27 | assetPath := NewEnvFlag(name).GetValue(getExecutableDir) 28 | defPath := filepath.Join(assetPath, file) 29 | for _, p := range []string{ 30 | defPath, 31 | filepath.Join("/usr/local/share/v2ray/", file), 32 | filepath.Join("/usr/share/v2ray/", file), 33 | } { 34 | if _, err := os.Stat(p); os.IsNotExist(err) { 35 | continue 36 | } 37 | 38 | // asset found 39 | return p 40 | } 41 | 42 | // asset not found, let the caller throw out the error 43 | return defPath 44 | } 45 | -------------------------------------------------------------------------------- /common/platform/windows.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | 3 | package platform 4 | 5 | import "path/filepath" 6 | 7 | func ExpandEnv(s string) string { 8 | // TODO 9 | return s 10 | } 11 | 12 | func LineSeparator() string { 13 | return "\r\n" 14 | } 15 | 16 | func GetToolLocation(file string) string { 17 | const name = "v2ray.location.tool" 18 | toolPath := EnvFlag{Name: name, AltName: NormalizeEnvName(name)}.GetValue(getExecutableDir) 19 | return filepath.Join(toolPath, file+".exe") 20 | } 21 | 22 | // GetAssetLocation search for `file` in the excutable dir 23 | func GetAssetLocation(file string) string { 24 | const name = "v2ray.location.asset" 25 | assetPath := NewEnvFlag(name).GetValue(getExecutableDir) 26 | return filepath.Join(assetPath, file) 27 | } 28 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /common/protocol/bittorrent/bittorrent.go: -------------------------------------------------------------------------------- 1 | package bittorrent 2 | 3 | import ( 4 | "errors" 5 | 6 | "v2ray.com/core/common" 7 | ) 8 | 9 | type SniffHeader struct { 10 | } 11 | 12 | func (h *SniffHeader) Protocol() string { 13 | return "bittorrent" 14 | } 15 | 16 | func (h *SniffHeader) Domain() string { 17 | return "" 18 | } 19 | 20 | var errNotBittorrent = errors.New("not bittorrent header") 21 | 22 | func SniffBittorrent(b []byte) (*SniffHeader, error) { 23 | if len(b) < 20 { 24 | return nil, common.ErrNoClue 25 | } 26 | 27 | if b[0] == 19 && string(b[1:20]) == "BitTorrent protocol" { 28 | return &SniffHeader{}, nil 29 | } 30 | 31 | return nil, errNotBittorrent 32 | } 33 | -------------------------------------------------------------------------------- /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/dns/errors.generated.go: -------------------------------------------------------------------------------- 1 | package dns 2 | 3 | import "v2ray.com/core/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 "v2ray.com/core/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/headers.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package v2ray.core.common.protocol; 4 | option csharp_namespace = "V2Ray.Core.Common.Protocol"; 5 | option go_package = "v2ray.com/core/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 | } 17 | 18 | message SecurityConfig { 19 | SecurityType type = 1; 20 | } 21 | -------------------------------------------------------------------------------- /common/protocol/id_test.go: -------------------------------------------------------------------------------- 1 | package protocol_test 2 | 3 | import ( 4 | "testing" 5 | 6 | . "v2ray.com/core/common/protocol" 7 | "v2ray.com/core/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/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/protocol/protocol.go: -------------------------------------------------------------------------------- 1 | package protocol // import "v2ray.com/core/common/protocol" 2 | 3 | //go:generate go run v2ray.com/core/common/errors/errorgen 4 | -------------------------------------------------------------------------------- /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 = "v2ray.com/core/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 | -------------------------------------------------------------------------------- /common/protocol/time.go: -------------------------------------------------------------------------------- 1 | package protocol 2 | 3 | import ( 4 | "time" 5 | 6 | "v2ray.com/core/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 | -------------------------------------------------------------------------------- /common/protocol/time_test.go: -------------------------------------------------------------------------------- 1 | package protocol_test 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | 7 | . "v2ray.com/core/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/protocol/tls/cert/.gitignore: -------------------------------------------------------------------------------- 1 | *.pem -------------------------------------------------------------------------------- /common/protocol/tls/cert/errors.generated.go: -------------------------------------------------------------------------------- 1 | package cert 2 | 3 | import "v2ray.com/core/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/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 | -------------------------------------------------------------------------------- /common/protocol/udp/packet.go: -------------------------------------------------------------------------------- 1 | package udp 2 | 3 | import ( 4 | "v2ray.com/core/common/buf" 5 | "v2ray.com/core/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 | -------------------------------------------------------------------------------- /common/protocol/udp/udp.go: -------------------------------------------------------------------------------- 1 | package udp 2 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 = "v2ray.com/core/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 | -------------------------------------------------------------------------------- /common/retry/errors.generated.go: -------------------------------------------------------------------------------- 1 | package retry 2 | 3 | import "v2ray.com/core/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/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/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/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 = "v2ray.com/core/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/serial/typed_message_test.go: -------------------------------------------------------------------------------- 1 | package serial_test 2 | 3 | import ( 4 | "testing" 5 | 6 | . "v2ray.com/core/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /common/signal/notifier_test.go: -------------------------------------------------------------------------------- 1 | package signal_test 2 | 3 | import ( 4 | "testing" 5 | 6 | . "v2ray.com/core/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 | -------------------------------------------------------------------------------- /common/signal/pubsub/pubsub_test.go: -------------------------------------------------------------------------------- 1 | package pubsub_test 2 | 3 | import ( 4 | "testing" 5 | 6 | . "v2ray.com/core/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 | -------------------------------------------------------------------------------- /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/stack/bytes.go: -------------------------------------------------------------------------------- 1 | package stack 2 | 3 | // TwoBytes is a [2]byte which is always allocated on stack. 4 | // 5 | //go:notinheap 6 | type TwoBytes [2]byte 7 | 8 | // EightBytes is a [8]byte which is always allocated on stack. 9 | // 10 | //go:notinheap 11 | type EightBytes [8]byte 12 | -------------------------------------------------------------------------------- /common/strmatcher/benchmark_test.go: -------------------------------------------------------------------------------- 1 | package strmatcher_test 2 | 3 | import ( 4 | "strconv" 5 | "testing" 6 | 7 | "v2ray.com/core/common" 8 | . "v2ray.com/core/common/strmatcher" 9 | ) 10 | 11 | func BenchmarkDomainMatcherGroup(b *testing.B) { 12 | g := new(DomainMatcherGroup) 13 | 14 | for i := 1; i <= 1024; i++ { 15 | g.Add(strconv.Itoa(i)+".v2ray.com", uint32(i)) 16 | } 17 | 18 | b.ResetTimer() 19 | for i := 0; i < b.N; i++ { 20 | _ = g.Match("0.v2ray.com") 21 | } 22 | } 23 | 24 | func BenchmarkFullMatcherGroup(b *testing.B) { 25 | g := new(FullMatcherGroup) 26 | 27 | for i := 1; i <= 1024; i++ { 28 | g.Add(strconv.Itoa(i)+".v2ray.com", uint32(i)) 29 | } 30 | 31 | b.ResetTimer() 32 | for i := 0; i < b.N; i++ { 33 | _ = g.Match("0.v2ray.com") 34 | } 35 | } 36 | 37 | func BenchmarkMarchGroup(b *testing.B) { 38 | g := new(MatcherGroup) 39 | for i := 1; i <= 1024; i++ { 40 | m, err := Domain.New(strconv.Itoa(i) + ".v2ray.com") 41 | common.Must(err) 42 | g.Add(m) 43 | } 44 | 45 | b.ResetTimer() 46 | for i := 0; i < b.N; i++ { 47 | _ = g.Match("0.v2ray.com") 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /common/strmatcher/full_matcher_test.go: -------------------------------------------------------------------------------- 1 | package strmatcher_test 2 | 3 | import ( 4 | "reflect" 5 | "testing" 6 | 7 | . "v2ray.com/core/common/strmatcher" 8 | ) 9 | 10 | func TestFullMatcherGroup(t *testing.T) { 11 | g := new(FullMatcherGroup) 12 | g.Add("v2ray.com", 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: "v2ray.com", 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("v2ray.com") 47 | if len(r) != 0 { 48 | t.Error("Expect [], but ", r) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /common/task/common.go: -------------------------------------------------------------------------------- 1 | package task 2 | 3 | import "v2ray.com/core/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 | -------------------------------------------------------------------------------- /common/task/periodic_test.go: -------------------------------------------------------------------------------- 1 | package task_test 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | 7 | "v2ray.com/core/common" 8 | . "v2ray.com/core/common/task" 9 | ) 10 | 11 | func TestPeriodicTaskStop(t *testing.T) { 12 | value := 0 13 | task := &Periodic{ 14 | Interval: time.Second * 2, 15 | Execute: func() error { 16 | value++ 17 | return nil 18 | }, 19 | } 20 | common.Must(task.Start()) 21 | time.Sleep(time.Second * 5) 22 | common.Must(task.Close()) 23 | if value != 3 { 24 | t.Fatal("expected 3, but got ", value) 25 | } 26 | time.Sleep(time.Second * 4) 27 | if value != 3 { 28 | t.Fatal("expected 3, but got ", value) 29 | } 30 | common.Must(task.Start()) 31 | time.Sleep(time.Second * 3) 32 | if value != 5 { 33 | t.Fatal("Expected 5, but ", value) 34 | } 35 | common.Must(task.Close()) 36 | } 37 | -------------------------------------------------------------------------------- /common/task/task.go: -------------------------------------------------------------------------------- 1 | package task 2 | 3 | import ( 4 | "context" 5 | 6 | "v2ray.com/core/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 | -------------------------------------------------------------------------------- /common/type_test.go: -------------------------------------------------------------------------------- 1 | package common_test 2 | 3 | import ( 4 | "context" 5 | "testing" 6 | 7 | . "v2ray.com/core/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 | var 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 | -------------------------------------------------------------------------------- /context.go: -------------------------------------------------------------------------------- 1 | // +build !confonly 2 | 3 | package core 4 | 5 | import ( 6 | "context" 7 | ) 8 | 9 | // V2rayKey is the key type of Instance in Context, exported for test. 10 | type V2rayKey int 11 | 12 | const v2rayKey V2rayKey = 1 13 | 14 | // FromContext returns an Instance from the given context, or nil if the context doesn't contain one. 15 | func FromContext(ctx context.Context) *Instance { 16 | if s, ok := ctx.Value(v2rayKey).(*Instance); ok { 17 | return s 18 | } 19 | return nil 20 | } 21 | 22 | // MustFromContext returns an Instance from the given context, or panics if not present. 23 | func MustFromContext(ctx context.Context) *Instance { 24 | v := FromContext(ctx) 25 | if v == nil { 26 | panic("V is not in context.") 27 | } 28 | return v 29 | } 30 | -------------------------------------------------------------------------------- /context_test.go: -------------------------------------------------------------------------------- 1 | package core_test 2 | 3 | import ( 4 | "context" 5 | "testing" 6 | 7 | . "v2ray.com/core" 8 | ) 9 | 10 | func TestContextPanic(t *testing.T) { 11 | defer func() { 12 | r := recover() 13 | if r == nil { 14 | t.Error("expect panic, but nil") 15 | } 16 | }() 17 | 18 | MustFromContext(context.Background()) 19 | } 20 | -------------------------------------------------------------------------------- /errors.generated.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import "v2ray.com/core/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 "v2ray.com/core/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/feature.go: -------------------------------------------------------------------------------- 1 | package features 2 | 3 | import "v2ray.com/core/common" 4 | 5 | //go:generate go run v2ray.com/core/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 | -------------------------------------------------------------------------------- /features/policy/default.go: -------------------------------------------------------------------------------- 1 | package policy 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | // DefaultManager is the implementation of the Manager. 8 | type DefaultManager struct{} 9 | 10 | // Type implements common.HasType. 11 | func (DefaultManager) Type() interface{} { 12 | return ManagerType() 13 | } 14 | 15 | // ForLevel implements Manager. 16 | func (DefaultManager) ForLevel(level uint32) Session { 17 | p := SessionDefault() 18 | if level == 1 { 19 | p.Timeouts.ConnectionIdle = time.Second * 600 20 | } 21 | return p 22 | } 23 | 24 | // ForSystem implements Manager. 25 | func (DefaultManager) ForSystem() System { 26 | return System{} 27 | } 28 | 29 | // Start implements common.Runnable. 30 | func (DefaultManager) Start() error { 31 | return nil 32 | } 33 | 34 | // Close implements common.Closable. 35 | func (DefaultManager) Close() error { 36 | return nil 37 | } 38 | -------------------------------------------------------------------------------- /features/routing/dispatcher.go: -------------------------------------------------------------------------------- 1 | package routing 2 | 3 | import ( 4 | "context" 5 | 6 | "v2ray.com/core/common/net" 7 | "v2ray.com/core/features" 8 | "v2ray.com/core/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 | -------------------------------------------------------------------------------- /features/routing/dns/errors.generated.go: -------------------------------------------------------------------------------- 1 | package dns 2 | 3 | import "v2ray.com/core/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 "v2ray.com/core/common/errors" 4 | 5 | type errPathObjHolder struct{} 6 | 7 | func newError(values ...interface{}) *errors.Error { 8 | return errors.New(values...).WithPathObj(errPathObjHolder{}) 9 | } 10 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module v2ray.com/core 2 | 3 | go 1.15 4 | 5 | require ( 6 | github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165 // indirect 7 | github.com/golang/mock v1.4.4 8 | github.com/golang/protobuf v1.4.2 9 | github.com/google/go-cmp v0.5.3 10 | github.com/gorilla/websocket v1.4.2 11 | github.com/lucas-clemente/quic-go v0.18.1 12 | github.com/miekg/dns v1.1.31 13 | github.com/pires/go-proxyproto v0.2.0 14 | github.com/seiflotfy/cuckoofilter v0.0.0-20200511222245-56093a4d3841 15 | github.com/stretchr/testify v1.8.1 16 | github.com/xiaokangwang/VSign v0.0.0-20200828155424-dc1c86b73fbf 17 | github.com/xtls/go v0.0.0-20201007031018-d42c13c57942 18 | go.starlark.net v0.0.0-20201006213952-227f4aabceb5 19 | golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 20 | golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0 21 | golang.org/x/sync v0.0.0-20200930132711-30421366ff76 22 | golang.org/x/sys v0.0.0-20201006155630-ac719f4daadf 23 | google.golang.org/grpc v1.32.0 24 | google.golang.org/protobuf v1.25.0 25 | h12.io/socks v1.0.1 26 | ) 27 | -------------------------------------------------------------------------------- /infra/bazel/BUILD: -------------------------------------------------------------------------------- 1 | filegroup( 2 | name = "rules", 3 | srcs = glob(["*.bzl"]), 4 | visibility = ["//visibility:public"], 5 | ) 6 | -------------------------------------------------------------------------------- /infra/bazel/matrix.bzl: -------------------------------------------------------------------------------- 1 | SUPPORTED_MATRIX = [ 2 | ("windows", "amd64", "0"), 3 | ("windows", "386", "0"), 4 | ("windows", "arm", "7"), 5 | ("darwin", "amd64", "0"), 6 | ("linux", "amd64", "0"), 7 | ("linux", "386", "0"), 8 | ("linux", "arm64", "0"), 9 | ("linux", "arm", "7"), 10 | ("linux", "arm", "6"), 11 | ("linux", "arm", "5"), 12 | ("linux", "mips64", "0"), 13 | ("linux", "mips", "0"), 14 | ("linux", "mips64le", "0"), 15 | ("linux", "mipsle", "0"), 16 | ("linux", "ppc64", "0"), 17 | ("linux", "ppc64le", "0"), 18 | ("linux", "riscv64", "0"), 19 | ("linux", "s390x", "0"), 20 | ("freebsd", "amd64", "0"), 21 | ("freebsd", "386", "0"), 22 | ("openbsd", "amd64", "0"), 23 | ("openbsd", "386", "0"), 24 | ("dragonfly", "amd64", "0"), 25 | ] 26 | -------------------------------------------------------------------------------- /infra/conf/api.go: -------------------------------------------------------------------------------- 1 | package conf 2 | 3 | import ( 4 | "strings" 5 | 6 | "v2ray.com/core/app/commander" 7 | loggerservice "v2ray.com/core/app/log/command" 8 | handlerservice "v2ray.com/core/app/proxyman/command" 9 | statsservice "v2ray.com/core/app/stats/command" 10 | "v2ray.com/core/common/serial" 11 | ) 12 | 13 | type ApiConfig struct { 14 | Tag string `json:"tag"` 15 | Services []string `json:"services"` 16 | } 17 | 18 | func (c *ApiConfig) Build() (*commander.Config, error) { 19 | if c.Tag == "" { 20 | return nil, newError("Api tag can't be empty.") 21 | } 22 | 23 | services := make([]*serial.TypedMessage, 0, 16) 24 | for _, s := range c.Services { 25 | switch strings.ToLower(s) { 26 | case "handlerservice": 27 | services = append(services, serial.ToTypedMessage(&handlerservice.Config{})) 28 | case "loggerservice": 29 | services = append(services, serial.ToTypedMessage(&loggerservice.Config{})) 30 | case "statsservice": 31 | services = append(services, serial.ToTypedMessage(&statsservice.Config{})) 32 | } 33 | } 34 | 35 | return &commander.Config{ 36 | Tag: c.Tag, 37 | Service: services, 38 | }, nil 39 | } 40 | -------------------------------------------------------------------------------- /infra/conf/blackhole_test.go: -------------------------------------------------------------------------------- 1 | package conf_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "v2ray.com/core/common/serial" 7 | . "v2ray.com/core/infra/conf" 8 | "v2ray.com/core/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/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 | -------------------------------------------------------------------------------- /infra/conf/command/errors.generated.go: -------------------------------------------------------------------------------- 1 | package command 2 | 3 | import "v2ray.com/core/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/conf.go: -------------------------------------------------------------------------------- 1 | package conf 2 | 3 | //go:generate go run v2ray.com/core/common/errors/errorgen 4 | -------------------------------------------------------------------------------- /infra/conf/dns_proxy.go: -------------------------------------------------------------------------------- 1 | package conf 2 | 3 | import ( 4 | "github.com/golang/protobuf/proto" 5 | "v2ray.com/core/common/net" 6 | "v2ray.com/core/proxy/dns" 7 | ) 8 | 9 | type DnsOutboundConfig struct { 10 | Network Network `json:"network"` 11 | Address *Address `json:"address"` 12 | Port uint16 `json:"port"` 13 | } 14 | 15 | func (c *DnsOutboundConfig) Build() (proto.Message, error) { 16 | config := &dns.Config{ 17 | Server: &net.Endpoint{ 18 | Network: c.Network.Build(), 19 | Port: uint32(c.Port), 20 | }, 21 | } 22 | if c.Address != nil { 23 | config.Server.Address = c.Address.Build() 24 | } 25 | return config, nil 26 | } 27 | -------------------------------------------------------------------------------- /infra/conf/dns_proxy_test.go: -------------------------------------------------------------------------------- 1 | package conf_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "v2ray.com/core/common/net" 7 | . "v2ray.com/core/infra/conf" 8 | "v2ray.com/core/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 | -------------------------------------------------------------------------------- /infra/conf/dokodemo.go: -------------------------------------------------------------------------------- 1 | package conf 2 | 3 | import ( 4 | "github.com/golang/protobuf/proto" 5 | "v2ray.com/core/proxy/dokodemo" 6 | ) 7 | 8 | type DokodemoConfig struct { 9 | Host *Address `json:"address"` 10 | PortValue uint16 `json:"port"` 11 | NetworkList *NetworkList `json:"network"` 12 | TimeoutValue uint32 `json:"timeout"` 13 | Redirect bool `json:"followRedirect"` 14 | UserLevel uint32 `json:"userLevel"` 15 | } 16 | 17 | func (v *DokodemoConfig) Build() (proto.Message, error) { 18 | config := new(dokodemo.Config) 19 | if v.Host != nil { 20 | config.Address = v.Host.Build() 21 | } 22 | config.Port = uint32(v.PortValue) 23 | config.Networks = v.NetworkList.Build() 24 | config.Timeout = v.TimeoutValue 25 | config.FollowRedirect = v.Redirect 26 | config.UserLevel = v.UserLevel 27 | return config, nil 28 | } 29 | -------------------------------------------------------------------------------- /infra/conf/dokodemo_test.go: -------------------------------------------------------------------------------- 1 | package conf_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "v2ray.com/core/common/net" 7 | . "v2ray.com/core/infra/conf" 8 | "v2ray.com/core/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 | Timeout: 10, 36 | FollowRedirect: true, 37 | UserLevel: 1, 38 | }, 39 | }, 40 | }) 41 | } 42 | -------------------------------------------------------------------------------- /infra/conf/errors.generated.go: -------------------------------------------------------------------------------- 1 | package conf 2 | 3 | import "v2ray.com/core/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/freedom_test.go: -------------------------------------------------------------------------------- 1 | package conf_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "v2ray.com/core/common/net" 7 | "v2ray.com/core/common/protocol" 8 | . "v2ray.com/core/infra/conf" 9 | "v2ray.com/core/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 | DomainStrategy: freedom.Config_AS_IS, 28 | Timeout: 10, 29 | DestinationOverride: &freedom.DestinationOverride{ 30 | Server: &protocol.ServerEndpoint{ 31 | Address: &net.IPOrDomain{ 32 | Address: &net.IPOrDomain_Ip{ 33 | Ip: []byte{127, 0, 0, 1}, 34 | }, 35 | }, 36 | Port: 3366, 37 | }, 38 | }, 39 | UserLevel: 1, 40 | }, 41 | }, 42 | }) 43 | } 44 | -------------------------------------------------------------------------------- /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 | "v2ray.com/core/common" 9 | . "v2ray.com/core/infra/conf" 10 | ) 11 | 12 | func loadJSON(creator func() Buildable) func(string) (proto.Message, error) { 13 | return func(s string) (proto.Message, error) { 14 | instance := creator() 15 | if err := json.Unmarshal([]byte(s), instance); err != nil { 16 | return nil, err 17 | } 18 | return instance.Build() 19 | } 20 | } 21 | 22 | type TestCase struct { 23 | Input string 24 | Parser func(string) (proto.Message, error) 25 | Output proto.Message 26 | } 27 | 28 | func runMultiTestCase(t *testing.T, testCases []TestCase) { 29 | for _, testCase := range testCases { 30 | actual, err := testCase.Parser(testCase.Input) 31 | common.Must(err) 32 | if !proto.Equal(actual, testCase.Output) { 33 | t.Fatalf("Failed in test case:\n%s\nActual:\n%v\nExpected:\n%v", testCase.Input, actual, testCase.Output) 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /infra/conf/http_test.go: -------------------------------------------------------------------------------- 1 | package conf_test 2 | 3 | import ( 4 | "testing" 5 | 6 | . "v2ray.com/core/infra/conf" 7 | "v2ray.com/core/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 | Timeout: 10, 36 | }, 37 | }, 38 | }) 39 | } 40 | -------------------------------------------------------------------------------- /infra/conf/mtproto_test.go: -------------------------------------------------------------------------------- 1 | package conf_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "v2ray.com/core/common/protocol" 7 | "v2ray.com/core/common/serial" 8 | . "v2ray.com/core/infra/conf" 9 | "v2ray.com/core/proxy/mtproto" 10 | ) 11 | 12 | func TestMTProtoServerConfig(t *testing.T) { 13 | creator := func() Buildable { 14 | return new(MTProtoServerConfig) 15 | } 16 | 17 | runMultiTestCase(t, []TestCase{ 18 | { 19 | Input: `{ 20 | "users": [{ 21 | "email": "love@v2ray.com", 22 | "level": 1, 23 | "secret": "b0cbcef5a486d9636472ac27f8e11a9d" 24 | }] 25 | }`, 26 | Parser: loadJSON(creator), 27 | Output: &mtproto.ServerConfig{ 28 | User: []*protocol.User{ 29 | { 30 | Email: "love@v2ray.com", 31 | Level: 1, 32 | Account: serial.ToTypedMessage(&mtproto.Account{ 33 | Secret: []byte{176, 203, 206, 245, 164, 134, 217, 99, 100, 114, 172, 39, 248, 225, 26, 157}, 34 | }), 35 | }, 36 | }, 37 | }, 38 | }, 39 | }) 40 | } 41 | -------------------------------------------------------------------------------- /infra/conf/policy_test.go: -------------------------------------------------------------------------------- 1 | package conf_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "v2ray.com/core/common" 7 | . "v2ray.com/core/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 := int32(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/reverse_test.go: -------------------------------------------------------------------------------- 1 | package conf_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "v2ray.com/core/app/reverse" 7 | "v2ray.com/core/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.v2ray.com" 21 | }] 22 | }`, 23 | Parser: loadJSON(creator), 24 | Output: &reverse.Config{ 25 | BridgeConfig: []*reverse.BridgeConfig{ 26 | {Tag: "test", Domain: "test.v2ray.com"}, 27 | }, 28 | }, 29 | }, 30 | { 31 | Input: `{ 32 | "portals": [{ 33 | "tag": "test", 34 | "domain": "test.v2ray.com" 35 | }] 36 | }`, 37 | Parser: loadJSON(creator), 38 | Output: &reverse.Config{ 39 | PortalConfig: []*reverse.PortalConfig{ 40 | {Tag: "test", Domain: "test.v2ray.com"}, 41 | }, 42 | }, 43 | }, 44 | }) 45 | } 46 | -------------------------------------------------------------------------------- /infra/conf/serial/errors.generated.go: -------------------------------------------------------------------------------- 1 | package serial 2 | 3 | import "v2ray.com/core/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/serial.go: -------------------------------------------------------------------------------- 1 | package serial 2 | 3 | //go:generate go run v2ray.com/core/common/errors/errorgen 4 | -------------------------------------------------------------------------------- /infra/conf/shadowsocks_test.go: -------------------------------------------------------------------------------- 1 | package conf_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "v2ray.com/core/common/net" 7 | "v2ray.com/core/common/protocol" 8 | "v2ray.com/core/common/serial" 9 | . "v2ray.com/core/infra/conf" 10 | "v2ray.com/core/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-128-cfb", 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_128_CFB, 29 | Password: "v2ray-password", 30 | }), 31 | }, 32 | Network: []net.Network{net.Network_TCP}, 33 | }, 34 | }, 35 | }) 36 | } 37 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /infra/control/control.go: -------------------------------------------------------------------------------- 1 | package control 2 | 3 | //go:generate go run v2ray.com/core/common/errors/errorgen 4 | -------------------------------------------------------------------------------- /infra/control/errors.generated.go: -------------------------------------------------------------------------------- 1 | package control 2 | 3 | import "v2ray.com/core/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/main/BUILD: -------------------------------------------------------------------------------- 1 | load("//infra/bazel:matrix.bzl", "SUPPORTED_MATRIX") 2 | load("//infra/control/main:targets.bzl", "gen_targets") 3 | 4 | package(default_visibility=["//visibility:public"]) 5 | 6 | gen_targets(SUPPORTED_MATRIX) 7 | -------------------------------------------------------------------------------- /infra/control/main/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "os" 7 | 8 | commlog "v2ray.com/core/common/log" 9 | // _ "v2ray.com/core/infra/conf/command" 10 | "v2ray.com/core/infra/control" 11 | ) 12 | 13 | func getCommandName() string { 14 | if len(os.Args) > 1 { 15 | return os.Args[1] 16 | } 17 | return "" 18 | } 19 | 20 | func main() { 21 | // let the v2ctl prints log at stderr 22 | commlog.RegisterHandler(commlog.NewLogger(commlog.CreateStderrLogWriter())) 23 | name := getCommandName() 24 | cmd := control.GetCommand(name) 25 | if cmd == nil { 26 | fmt.Fprintln(os.Stderr, "Unknown command:", name) 27 | fmt.Fprintln(os.Stderr) 28 | 29 | fmt.Println("v2ctl ") 30 | fmt.Println("Available commands:") 31 | control.PrintUsage() 32 | return 33 | } 34 | 35 | if err := cmd.Execute(os.Args[2:]); err != nil { 36 | hasError := false 37 | if err != flag.ErrHelp { 38 | fmt.Fprintln(os.Stderr, err.Error()) 39 | fmt.Fprintln(os.Stderr) 40 | hasError = true 41 | } 42 | 43 | for _, line := range cmd.Description().Usage { 44 | fmt.Println(line) 45 | } 46 | 47 | if hasError { 48 | os.Exit(-1) 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /infra/control/uuid.go: -------------------------------------------------------------------------------- 1 | package control 2 | 3 | import ( 4 | "fmt" 5 | 6 | "v2ray.com/core/common" 7 | "v2ray.com/core/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 UUIDs", 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 | -------------------------------------------------------------------------------- /main/BUILD: -------------------------------------------------------------------------------- 1 | load("//infra/bazel:matrix.bzl", "SUPPORTED_MATRIX") 2 | load("//main:targets.bzl", "gen_targets") 3 | 4 | package(default_visibility=["//visibility:public"]) 5 | 6 | gen_targets(SUPPORTED_MATRIX) 7 | -------------------------------------------------------------------------------- /main/confloader/confloader.go: -------------------------------------------------------------------------------- 1 | package confloader 2 | 3 | import ( 4 | "io" 5 | "os" 6 | ) 7 | 8 | type configFileLoader func(string) (io.Reader, error) 9 | type extconfigLoader func([]string) (io.Reader, error) 10 | 11 | var ( 12 | EffectiveConfigFileLoader configFileLoader 13 | EffectiveExtConfigLoader extconfigLoader 14 | ) 15 | 16 | // LoadConfig reads from a path/url/stdin 17 | // actual work is in external module 18 | func LoadConfig(file string) (io.Reader, error) { 19 | if EffectiveConfigFileLoader == nil { 20 | newError("external config module not loaded, reading from stdin").AtInfo().WriteToLog() 21 | return os.Stdin, nil 22 | } 23 | return EffectiveConfigFileLoader(file) 24 | } 25 | 26 | // LoadExtConfig calls v2ctl to handle multiple config 27 | // the actual work also in external module 28 | func LoadExtConfig(files []string) (io.Reader, error) { 29 | if EffectiveExtConfigLoader == nil { 30 | return nil, newError("external config module not loaded").AtError() 31 | } 32 | 33 | return EffectiveExtConfigLoader(files) 34 | } 35 | -------------------------------------------------------------------------------- /main/confloader/errors.generated.go: -------------------------------------------------------------------------------- 1 | package confloader 2 | 3 | import "v2ray.com/core/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 "v2ray.com/core/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/distro/debug/debug.go: -------------------------------------------------------------------------------- 1 | package debug 2 | 3 | import _ "net/http/pprof" 4 | import "net/http" 5 | 6 | func init() { 7 | go func() { 8 | http.ListenAndServe(":6060", nil) 9 | }() 10 | } 11 | -------------------------------------------------------------------------------- /main/errors.generated.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "v2ray.com/core/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/config_json.go: -------------------------------------------------------------------------------- 1 | package json 2 | 3 | //go:generate go run v2ray.com/core/common/errors/errorgen 4 | 5 | import ( 6 | "io" 7 | 8 | "v2ray.com/core" 9 | "v2ray.com/core/common" 10 | "v2ray.com/core/common/cmdarg" 11 | "v2ray.com/core/infra/conf/serial" 12 | "v2ray.com/core/main/confloader" 13 | ) 14 | 15 | func init() { 16 | common.Must(core.RegisterConfigLoader(&core.ConfigFormat{ 17 | Name: "JSON", 18 | Extension: []string{"json"}, 19 | Loader: func(input interface{}) (*core.Config, error) { 20 | switch v := input.(type) { 21 | case cmdarg.Arg: 22 | r, err := confloader.LoadExtConfig(v) 23 | if err != nil { 24 | return nil, newError("failed to execute v2ctl to convert config file.").Base(err).AtWarning() 25 | } 26 | return core.LoadConfig("protobuf", "", r) 27 | case io.Reader: 28 | return serial.LoadJSONConfig(v) 29 | default: 30 | return nil, newError("unknow type") 31 | } 32 | }, 33 | })) 34 | } 35 | -------------------------------------------------------------------------------- /main/json/errors.generated.go: -------------------------------------------------------------------------------- 1 | package json 2 | 3 | import "v2ray.com/core/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 "v2ray.com/core/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/jsonem.go: -------------------------------------------------------------------------------- 1 | package jsonem 2 | 3 | import ( 4 | "io" 5 | 6 | "v2ray.com/core" 7 | "v2ray.com/core/common" 8 | "v2ray.com/core/common/cmdarg" 9 | "v2ray.com/core/infra/conf" 10 | "v2ray.com/core/infra/conf/serial" 11 | "v2ray.com/core/main/confloader" 12 | ) 13 | 14 | func init() { 15 | common.Must(core.RegisterConfigLoader(&core.ConfigFormat{ 16 | Name: "JSON", 17 | Extension: []string{"json"}, 18 | Loader: func(input interface{}) (*core.Config, error) { 19 | switch v := input.(type) { 20 | case cmdarg.Arg: 21 | cf := &conf.Config{} 22 | for _, arg := range v { 23 | newError("Reading config: ", arg).AtInfo().WriteToLog() 24 | r, err := confloader.LoadConfig(arg) 25 | common.Must(err) 26 | c, err := serial.DecodeJSONConfig(r) 27 | common.Must(err) 28 | cf.Override(c, arg) 29 | } 30 | return cf.Build() 31 | case io.Reader: 32 | return serial.LoadJSONConfig(v) 33 | default: 34 | return nil, newError("unknow type") 35 | } 36 | }, 37 | })) 38 | } 39 | -------------------------------------------------------------------------------- /main/main_test.go: -------------------------------------------------------------------------------- 1 | // +build coveragemain 2 | 3 | package main 4 | 5 | import ( 6 | "testing" 7 | ) 8 | 9 | func TestRunMainForCoverage(t *testing.T) { 10 | main() 11 | } 12 | -------------------------------------------------------------------------------- /mocks.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | //go:generate go run github.com/golang/mock/mockgen -package mocks -destination testing/mocks/io.go -mock_names Reader=Reader,Writer=Writer io Reader,Writer 4 | //go:generate go run github.com/golang/mock/mockgen -package mocks -destination testing/mocks/log.go -mock_names Handler=LogHandler v2ray.com/core/common/log Handler 5 | //go:generate go run github.com/golang/mock/mockgen -package mocks -destination testing/mocks/mux.go -mock_names ClientWorkerFactory=MuxClientWorkerFactory v2ray.com/core/common/mux ClientWorkerFactory 6 | //go:generate go run github.com/golang/mock/mockgen -package mocks -destination testing/mocks/dns.go -mock_names Client=DNSClient v2ray.com/core/features/dns Client 7 | //go:generate go run github.com/golang/mock/mockgen -package mocks -destination testing/mocks/outbound.go -mock_names Manager=OutboundManager,HandlerSelector=OutboundHandlerSelector v2ray.com/core/features/outbound Manager,HandlerSelector 8 | //go:generate go run github.com/golang/mock/mockgen -package mocks -destination testing/mocks/proxy.go -mock_names Inbound=ProxyInbound,Outbound=ProxyOutbound v2ray.com/core/proxy Inbound,Outbound 9 | -------------------------------------------------------------------------------- /proto.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | //go:generate go install -v google.golang.org/protobuf/cmd/protoc-gen-go 4 | //go:generate go install -v google.golang.org/grpc/cmd/protoc-gen-go-grpc 5 | //go:generate go install -v github.com/gogo/protobuf/protoc-gen-gofast 6 | //go:generate go run ./infra/vprotogen/main.go 7 | 8 | import "path/filepath" 9 | 10 | // ProtoFilesUsingProtocGenGoFast is the map of Proto files 11 | // that use `protoc-gen-gofast` to generate pb.go files 12 | var ProtoFilesUsingProtocGenGoFast = map[string]bool{"proxy/vless/encoding/addons.proto": true} 13 | 14 | // ProtocMap is the map of paths to `protoc` binary excutable files of specific platform 15 | var ProtocMap = map[string]string{ 16 | "windows": filepath.Join(".dev", "protoc", "windows", "protoc.exe"), 17 | "darwin": filepath.Join(".dev", "protoc", "macos", "protoc"), 18 | "linux": filepath.Join(".dev", "protoc", "linux", "protoc"), 19 | } 20 | -------------------------------------------------------------------------------- /proxy/blackhole/blackhole_test.go: -------------------------------------------------------------------------------- 1 | package blackhole_test 2 | 3 | import ( 4 | "context" 5 | "testing" 6 | 7 | "v2ray.com/core/common" 8 | "v2ray.com/core/common/buf" 9 | "v2ray.com/core/common/serial" 10 | "v2ray.com/core/proxy/blackhole" 11 | "v2ray.com/core/transport" 12 | "v2ray.com/core/transport/pipe" 13 | ) 14 | 15 | func TestBlackholeHTTPResponse(t *testing.T) { 16 | handler, err := blackhole.New(context.Background(), &blackhole.Config{ 17 | Response: serial.ToTypedMessage(&blackhole.HTTPResponse{}), 18 | }) 19 | common.Must(err) 20 | 21 | reader, writer := pipe.New(pipe.WithoutSizeLimit()) 22 | 23 | var mb buf.MultiBuffer 24 | var rerr error 25 | go func() { 26 | b, e := reader.ReadMultiBuffer() 27 | mb = b 28 | rerr = e 29 | }() 30 | 31 | link := transport.Link{ 32 | Reader: reader, 33 | Writer: writer, 34 | } 35 | common.Must(handler.Process(context.Background(), &link, nil)) 36 | common.Must(rerr) 37 | if mb.IsEmpty() { 38 | t.Error("expect http response, but nothing") 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /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 = "v2ray.com/core/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 | -------------------------------------------------------------------------------- /proxy/blackhole/config_test.go: -------------------------------------------------------------------------------- 1 | package blackhole_test 2 | 3 | import ( 4 | "bufio" 5 | "net/http" 6 | "testing" 7 | 8 | "v2ray.com/core/common" 9 | "v2ray.com/core/common/buf" 10 | . "v2ray.com/core/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 | if response.StatusCode != 403 { 23 | t.Error("expected status code 403, but got ", response.StatusCode) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /proxy/blackhole/errors.generated.go: -------------------------------------------------------------------------------- 1 | package blackhole 2 | 3 | import "v2ray.com/core/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/config.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package v2ray.core.proxy.dns; 4 | option csharp_namespace = "V2Ray.Core.Proxy.Dns"; 5 | option go_package = "v2ray.com/core/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 | -------------------------------------------------------------------------------- /proxy/dns/errors.generated.go: -------------------------------------------------------------------------------- 1 | package dns 2 | 3 | import "v2ray.com/core/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/config.go: -------------------------------------------------------------------------------- 1 | package dokodemo 2 | 3 | import ( 4 | "v2ray.com/core/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 | -------------------------------------------------------------------------------- /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 = "v2ray.com/core/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 | uint32 timeout = 4 [deprecated = true]; 23 | bool follow_redirect = 5; 24 | uint32 user_level = 6; 25 | } 26 | -------------------------------------------------------------------------------- /proxy/dokodemo/errors.generated.go: -------------------------------------------------------------------------------- 1 | package dokodemo 2 | 3 | import "v2ray.com/core/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/config.go: -------------------------------------------------------------------------------- 1 | package freedom 2 | 3 | func (c *Config) useIP() bool { 4 | return c.DomainStrategy == Config_USE_IP || c.DomainStrategy == Config_USE_IP4 || c.DomainStrategy == Config_USE_IP6 5 | } 6 | -------------------------------------------------------------------------------- /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 = "v2ray.com/core/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 | enum DomainStrategy { 17 | AS_IS = 0; 18 | USE_IP = 1; 19 | USE_IP4 = 2; 20 | USE_IP6 = 3; 21 | } 22 | DomainStrategy domain_strategy = 1; 23 | uint32 timeout = 2 [deprecated = true]; 24 | DestinationOverride destination_override = 3; 25 | uint32 user_level = 4; 26 | } 27 | -------------------------------------------------------------------------------- /proxy/freedom/errors.generated.go: -------------------------------------------------------------------------------- 1 | package freedom 2 | 3 | import "v2ray.com/core/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/config.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | import ( 4 | "v2ray.com/core/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 | -------------------------------------------------------------------------------- /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 = "v2ray.com/core/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 | uint32 timeout = 1 [deprecated = true]; 19 | map accounts = 2; 20 | bool allow_transparent = 3; 21 | uint32 user_level = 4; 22 | } 23 | 24 | // ClientConfig is the protobuf config for HTTP proxy client. 25 | message ClientConfig { 26 | // Sever is a list of HTTP server addresses. 27 | repeated v2ray.core.common.protocol.ServerEndpoint server = 1; 28 | } 29 | -------------------------------------------------------------------------------- /proxy/http/errors.generated.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | import "v2ray.com/core/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/http.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | //go:generate go run v2ray.com/core/common/errors/errorgen 4 | -------------------------------------------------------------------------------- /proxy/mtproto/config.go: -------------------------------------------------------------------------------- 1 | package mtproto 2 | 3 | import ( 4 | "v2ray.com/core/common/protocol" 5 | ) 6 | 7 | func (a *Account) Equals(another protocol.Account) bool { 8 | aa, ok := another.(*Account) 9 | if !ok { 10 | return false 11 | } 12 | 13 | if len(a.Secret) != len(aa.Secret) { 14 | return false 15 | } 16 | 17 | for i, v := range a.Secret { 18 | if v != aa.Secret[i] { 19 | return false 20 | } 21 | } 22 | 23 | return true 24 | } 25 | -------------------------------------------------------------------------------- /proxy/mtproto/config.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package v2ray.core.proxy.mtproto; 4 | option csharp_namespace = "V2Ray.Core.Proxy.Mtproto"; 5 | option go_package = "v2ray.com/core/proxy/mtproto"; 6 | option java_package = "com.v2ray.core.proxy.mtproto"; 7 | option java_multiple_files = true; 8 | 9 | import "common/protocol/user.proto"; 10 | 11 | message Account { 12 | bytes secret = 1; 13 | } 14 | 15 | message ServerConfig { 16 | // User is a list of users that allowed to connect to this inbound. 17 | // Although this is a repeated field, only the first user is effective for 18 | // now. 19 | repeated v2ray.core.common.protocol.User user = 1; 20 | } 21 | 22 | message ClientConfig {} 23 | -------------------------------------------------------------------------------- /proxy/mtproto/errors.generated.go: -------------------------------------------------------------------------------- 1 | package mtproto 2 | 3 | import "v2ray.com/core/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/mtproto/mtproto.go: -------------------------------------------------------------------------------- 1 | package mtproto 2 | 3 | //go:generate go run v2ray.com/core/common/errors/errorgen 4 | -------------------------------------------------------------------------------- /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 | "v2ray.com/core/common" 10 | "v2ray.com/core/common/buf" 11 | "v2ray.com/core/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 | -------------------------------------------------------------------------------- /proxy/shadowsocks/errors.generated.go: -------------------------------------------------------------------------------- 1 | package shadowsocks 2 | 3 | import "v2ray.com/core/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/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 v2ray.com/core/common/errors/errorgen 9 | -------------------------------------------------------------------------------- /proxy/socks/config.go: -------------------------------------------------------------------------------- 1 | // +build !confonly 2 | 3 | package socks 4 | 5 | import "v2ray.com/core/common/protocol" 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 (c *ServerConfig) HasAccount(username, password string) bool { 19 | if c.Accounts == nil { 20 | return false 21 | } 22 | storedPassed, found := c.Accounts[username] 23 | if !found { 24 | return false 25 | } 26 | return storedPassed == password 27 | } 28 | -------------------------------------------------------------------------------- /proxy/socks/errors.generated.go: -------------------------------------------------------------------------------- 1 | package socks 2 | 3 | import "v2ray.com/core/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/socks.go: -------------------------------------------------------------------------------- 1 | // Package socks provides implements of Socks protocol 4, 4a and 5. 2 | package socks 3 | 4 | //go:generate go run v2ray.com/core/common/errors/errorgen 5 | -------------------------------------------------------------------------------- /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 = "v2ray.com/core/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 | -------------------------------------------------------------------------------- /proxy/trojan/errors.generated.go: -------------------------------------------------------------------------------- 1 | package trojan 2 | 3 | import "v2ray.com/core/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/trojan.go: -------------------------------------------------------------------------------- 1 | package trojan 2 | -------------------------------------------------------------------------------- /proxy/trojan/validator.go: -------------------------------------------------------------------------------- 1 | package trojan 2 | 3 | import ( 4 | "sync" 5 | 6 | "v2ray.com/core/common/protocol" 7 | ) 8 | 9 | // Validator stores valid trojan users 10 | type Validator struct { 11 | users sync.Map 12 | } 13 | 14 | // Add a trojan user 15 | func (v *Validator) Add(u *protocol.MemoryUser) error { 16 | user := u.Account.(*MemoryAccount) 17 | v.users.Store(hexString(user.Key), u) 18 | return nil 19 | } 20 | 21 | // Get user with hashed key, nil if user doesn't exist. 22 | func (v *Validator) Get(hash string) *protocol.MemoryUser { 23 | u, _ := v.users.Load(hash) 24 | if u != nil { 25 | return u.(*protocol.MemoryUser) 26 | } 27 | return nil 28 | } 29 | -------------------------------------------------------------------------------- /proxy/vless/account.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package v2ray.core.proxy.vless; 4 | option csharp_namespace = "V2Ray.Core.Proxy.Vless"; 5 | option go_package = "v2ray.com/core/proxy/vless"; 6 | option java_package = "com.v2ray.core.proxy.vless"; 7 | option java_multiple_files = true; 8 | 9 | message Account { 10 | // ID of the account, in the form of a UUID, e.g., "66ad4540-b58c-4ad2-9926-ea63445a9b57". 11 | string id = 1; 12 | // Flow settings. May be "xtls-rprx-origin". 13 | string flow = 2; 14 | // Encryption settings. Only applies to client side, and only accepts "none" for now. 15 | string encryption = 3; 16 | } 17 | -------------------------------------------------------------------------------- /proxy/vless/encoding/addons.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package v2ray.core.proxy.vless.encoding; 4 | option csharp_namespace = "V2Ray.Core.Proxy.Vless.Encoding"; 5 | option go_package = "v2ray.com/core/proxy/vless/encoding"; 6 | option java_package = "com.v2ray.core.proxy.vless.encoding"; 7 | option java_multiple_files = true; 8 | 9 | message Addons { 10 | string Flow = 1; 11 | bytes Seed = 2; 12 | } 13 | -------------------------------------------------------------------------------- /proxy/vless/encoding/errors.generated.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import "v2ray.com/core/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/vless/errors.generated.go: -------------------------------------------------------------------------------- 1 | package vless 2 | 3 | import "v2ray.com/core/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/vless/inbound/config.go: -------------------------------------------------------------------------------- 1 | // +build !confonly 2 | 3 | package inbound 4 | -------------------------------------------------------------------------------- /proxy/vless/inbound/config.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package v2ray.core.proxy.vless.inbound; 4 | option csharp_namespace = "V2Ray.Core.Proxy.Vless.Inbound"; 5 | option go_package = "v2ray.com/core/proxy/vless/inbound"; 6 | option java_package = "com.v2ray.core.proxy.vless.inbound"; 7 | option java_multiple_files = true; 8 | 9 | import "common/protocol/user.proto"; 10 | 11 | message Fallback { 12 | string alpn = 1; 13 | string path = 2; 14 | string type = 3; 15 | string dest = 4; 16 | uint64 xver = 5; 17 | } 18 | 19 | message Config { 20 | repeated v2ray.core.common.protocol.User clients = 1; 21 | // Decryption settings. Only applies to server side, and only accepts "none" 22 | // for now. 23 | string decryption = 2; 24 | repeated Fallback fallbacks = 3; 25 | } 26 | -------------------------------------------------------------------------------- /proxy/vless/inbound/errors.generated.go: -------------------------------------------------------------------------------- 1 | package inbound 2 | 3 | import "v2ray.com/core/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/vless/outbound/config.go: -------------------------------------------------------------------------------- 1 | // +build !confonly 2 | 3 | package outbound 4 | -------------------------------------------------------------------------------- /proxy/vless/outbound/config.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package v2ray.core.proxy.vless.outbound; 4 | option csharp_namespace = "V2Ray.Core.Proxy.Vless.Outbound"; 5 | option go_package = "v2ray.com/core/proxy/vless/outbound"; 6 | option java_package = "com.v2ray.core.proxy.vless.outbound"; 7 | option java_multiple_files = true; 8 | 9 | import "common/protocol/server_spec.proto"; 10 | 11 | message Config { 12 | repeated v2ray.core.common.protocol.ServerEndpoint vnext = 1; 13 | } 14 | -------------------------------------------------------------------------------- /proxy/vless/outbound/errors.generated.go: -------------------------------------------------------------------------------- 1 | package outbound 2 | 3 | import "v2ray.com/core/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/vless/vless.go: -------------------------------------------------------------------------------- 1 | // Package vless contains the implementation of VLess protocol and transportation. 2 | // 3 | // VLess contains both inbound and outbound connections. VLess inbound is usually used on servers 4 | // together with 'freedom' to talk to final destination, while VLess outbound is usually used on 5 | // clients with 'socks' for proxying. 6 | package vless 7 | 8 | //go:generate go run v2ray.com/core/common/errors/errorgen 9 | 10 | const ( 11 | XRO = "xtls-rprx-origin" 12 | XRD = "xtls-rprx-direct" 13 | ) 14 | -------------------------------------------------------------------------------- /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 = "v2ray.com/core/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 | // Number of alternative IDs. Client and server must share the same number. 16 | uint32 alter_id = 2; 17 | // Security settings. Only applies to client side. 18 | v2ray.core.common.protocol.SecurityConfig security_settings = 3; 19 | // Define tests enabled for this account 20 | string tests_enabled = 4; 21 | } 22 | -------------------------------------------------------------------------------- /proxy/vmess/aead/consts.go: -------------------------------------------------------------------------------- 1 | package aead 2 | 3 | const KDFSaltConst_AuthIDEncryptionKey = "AES Auth ID Encryption" 4 | 5 | const KDFSaltConst_AEADRespHeaderLenKey = "AEAD Resp Header Len Key" 6 | 7 | const KDFSaltConst_AEADRespHeaderLenIV = "AEAD Resp Header Len IV" 8 | 9 | const KDFSaltConst_AEADRespHeaderPayloadKey = "AEAD Resp Header Key" 10 | 11 | const KDFSaltConst_AEADRespHeaderPayloadIV = "AEAD Resp Header IV" 12 | 13 | const KDFSaltConst_VMessAEADKDF = "VMess AEAD KDF" 14 | 15 | const KDFSaltConst_VMessHeaderPayloadAEADKey = "VMess Header AEAD Key" 16 | 17 | const KDFSaltConst_VMessHeaderPayloadAEADIV = "VMess Header AEAD Nonce" 18 | 19 | const KDFSaltConst_VMessHeaderPayloadLengthAEADKey = "VMess Header AEAD Key_Length" 20 | 21 | const KDFSaltConst_VMessHeaderPayloadLengthAEADIV = "VMess Header AEAD Nonce_Length" 22 | -------------------------------------------------------------------------------- /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 | hmacf := hmac.New(func() hash.Hash { 11 | return sha256.New() 12 | }, []byte(KDFSaltConst_VMessAEADKDF)) 13 | 14 | for _, v := range path { 15 | hmacf = hmac.New(func() hash.Hash { 16 | return hmacf 17 | }, []byte(v)) 18 | } 19 | hmacf.Write(key) 20 | return hmacf.Sum(nil) 21 | } 22 | 23 | func KDF16(key []byte, path ...string) []byte { 24 | r := KDF(key, path...) 25 | return r[:16] 26 | } 27 | -------------------------------------------------------------------------------- /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 | "v2ray.com/core/common" 10 | . "v2ray.com/core/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 | -------------------------------------------------------------------------------- /proxy/vmess/encoding/commands_test.go: -------------------------------------------------------------------------------- 1 | package encoding_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/google/go-cmp/cmp" 7 | 8 | "v2ray.com/core/common" 9 | "v2ray.com/core/common/buf" 10 | "v2ray.com/core/common/protocol" 11 | "v2ray.com/core/common/uuid" 12 | . "v2ray.com/core/proxy/vmess/encoding" 13 | ) 14 | 15 | func TestSwitchAccount(t *testing.T) { 16 | sa := &protocol.CommandSwitchAccount{ 17 | Port: 1234, 18 | ID: uuid.New(), 19 | AlterIds: 1024, 20 | Level: 128, 21 | ValidMin: 16, 22 | } 23 | 24 | buffer := buf.New() 25 | common.Must(MarshalCommand(sa, buffer)) 26 | 27 | cmd, err := UnmarshalCommand(1, buffer.BytesFrom(2)) 28 | common.Must(err) 29 | 30 | sa2, ok := cmd.(*protocol.CommandSwitchAccount) 31 | if !ok { 32 | t.Fatal("failed to convert command to CommandSwitchAccount") 33 | } 34 | if r := cmp.Diff(sa2, sa); r != "" { 35 | t.Error(r) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /proxy/vmess/encoding/encoding.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import ( 4 | "v2ray.com/core/common/net" 5 | "v2ray.com/core/common/protocol" 6 | ) 7 | 8 | //go:generate go run v2ray.com/core/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 | -------------------------------------------------------------------------------- /proxy/vmess/encoding/errors.generated.go: -------------------------------------------------------------------------------- 1 | package encoding 2 | 3 | import "v2ray.com/core/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 "v2ray.com/core/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/config.go: -------------------------------------------------------------------------------- 1 | // +build !confonly 2 | 3 | package inbound 4 | 5 | // GetDefaultValue returns default settings of DefaultConfig. 6 | func (c *Config) GetDefaultValue() *DefaultConfig { 7 | if c.GetDefault() == nil { 8 | return &DefaultConfig{ 9 | AlterId: 32, 10 | Level: 0, 11 | } 12 | } 13 | return c.Default 14 | } 15 | -------------------------------------------------------------------------------- /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 = "v2ray.com/core/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 alter_id = 1; 17 | uint32 level = 2; 18 | } 19 | 20 | message Config { 21 | repeated v2ray.core.common.protocol.User user = 1; 22 | DefaultConfig default = 2; 23 | DetourConfig detour = 3; 24 | bool secure_encryption_only = 4; 25 | } 26 | -------------------------------------------------------------------------------- /proxy/vmess/inbound/errors.generated.go: -------------------------------------------------------------------------------- 1 | package inbound 2 | 3 | import "v2ray.com/core/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/config.go: -------------------------------------------------------------------------------- 1 | package outbound 2 | -------------------------------------------------------------------------------- /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 = "v2ray.com/core/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 | repeated v2ray.core.common.protocol.ServerEndpoint Receiver = 1; 13 | } 14 | -------------------------------------------------------------------------------- /proxy/vmess/outbound/errors.generated.go: -------------------------------------------------------------------------------- 1 | package outbound 2 | 3 | import "v2ray.com/core/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/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 v2ray.com/core/common/errors/errorgen 9 | -------------------------------------------------------------------------------- /proxy/vmess/vmessCtxInterface.go: -------------------------------------------------------------------------------- 1 | package vmess 2 | 3 | // example 4 | const AlterID = "VMessCtxInterface_AlterID" 5 | -------------------------------------------------------------------------------- /release/config/geoip.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/v2ray/v2ray-core/d80440f3d57b45c829dbf513306f7adf9a0f3f76/release/config/geoip.dat -------------------------------------------------------------------------------- /release/config/geosite.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/v2ray/v2ray-core/d80440f3d57b45c829dbf513306f7adf9a0f3f76/release/config/geosite.dat -------------------------------------------------------------------------------- /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=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/local/bin/v2ray -config /usr/local/etc/v2ray/config.json 12 | Restart=on-failure 13 | RestartPreventExitStatus=23 14 | 15 | [Install] 16 | WantedBy=multi-user.target 17 | -------------------------------------------------------------------------------- /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=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/local/bin/v2ray -config /usr/local/etc/v2ray/%i.json 12 | Restart=on-failure 13 | RestartPreventExitStatus=23 14 | 15 | [Install] 16 | WantedBy=multi-user.target 17 | -------------------------------------------------------------------------------- /release/config/vpoint_socks_vmess.json: -------------------------------------------------------------------------------- 1 | { 2 | "log": { 3 | "loglevel": "warning" 4 | }, 5 | "inbounds": [{ 6 | "port": 1080, 7 | "listen": "127.0.0.1", 8 | "protocol": "socks", 9 | "settings": { 10 | "auth": "noauth", 11 | "udp": false, 12 | "ip": "127.0.0.1" 13 | } 14 | }], 15 | "outbounds": [{ 16 | "protocol": "freedom", 17 | "settings": {}, 18 | "tag": "direct" 19 | }], 20 | "policy": { 21 | "levels": { 22 | "0": {"uplinkOnly": 0} 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /release/config/vpoint_vmess_freedom.json: -------------------------------------------------------------------------------- 1 | { 2 | "inbounds": [{ 3 | "port": 10086, 4 | "protocol": "vmess", 5 | "settings": { 6 | "clients": [ 7 | { 8 | "id": "23ad6b10-8d1a-40f7-8ad0-e3e35cd38297", 9 | "level": 1, 10 | "alterId": 64 11 | } 12 | ] 13 | } 14 | }], 15 | "outbounds": [{ 16 | "protocol": "freedom", 17 | "settings": {} 18 | },{ 19 | "protocol": "blackhole", 20 | "settings": {}, 21 | "tag": "blocked" 22 | }], 23 | "routing": { 24 | "rules": [ 25 | { 26 | "type": "field", 27 | "ip": ["geoip:private"], 28 | "outboundTag": "blocked" 29 | } 30 | ] 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /release/mapping.bzl: -------------------------------------------------------------------------------- 1 | def gen_mappings(os, arch, ver): 2 | return { 3 | "v2ray_core/release/config": "", 4 | "v2ray_core/main/" + os + "/" + arch + "/" + ver: "", 5 | "v2ray_core/infra/control/main/" + os + "/" + arch + "/" + ver : "", 6 | } 7 | -------------------------------------------------------------------------------- /release/mutilate/removeVSign.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | export VROOT=$(dirname "${BASH_SOURCE[0]}")/../../ 4 | 5 | rm $VROOT/infra/control/verify.go 6 | 7 | sed -i '/VSign/d' $VROOT/go.mod 8 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /release/requestsign_github.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | export SIGN_VERSION=$(cat $GITHUB_EVENT_PATH| jq -r ".release.tag_name") 4 | 5 | echo $SIGN_VERSION 6 | 7 | $GITHUB_WORKSPACE/release/requestsign.sh 8 | -------------------------------------------------------------------------------- /testing/scenarios/common_coverage.go: -------------------------------------------------------------------------------- 1 | // +build coverage 2 | 3 | package scenarios 4 | 5 | import ( 6 | "bytes" 7 | "os" 8 | "os/exec" 9 | 10 | "v2ray.com/core/common/uuid" 11 | ) 12 | 13 | func BuildV2Ray() error { 14 | genTestBinaryPath() 15 | if _, err := os.Stat(testBinaryPath); err == nil { 16 | return nil 17 | } 18 | 19 | cmd := exec.Command("go", "test", "-tags", "coverage coveragemain", "-coverpkg", "v2ray.com/core/...", "-c", "-o", testBinaryPath, GetSourcePath()) 20 | return cmd.Run() 21 | } 22 | 23 | func RunV2RayProtobuf(config []byte) *exec.Cmd { 24 | genTestBinaryPath() 25 | 26 | covDir := os.Getenv("V2RAY_COV") 27 | os.MkdirAll(covDir, os.ModeDir) 28 | randomID := uuid.New() 29 | profile := randomID.String() + ".out" 30 | proc := exec.Command(testBinaryPath, "-config=stdin:", "-format=pb", "-test.run", "TestRunMainForCoverage", "-test.coverprofile", profile, "-test.outputdir", covDir) 31 | proc.Stdin = bytes.NewBuffer(config) 32 | proc.Stderr = os.Stderr 33 | proc.Stdout = os.Stdout 34 | 35 | return proc 36 | } 37 | -------------------------------------------------------------------------------- /testing/scenarios/common_regular.go: -------------------------------------------------------------------------------- 1 | // +build !coverage 2 | 3 | package scenarios 4 | 5 | import ( 6 | "bytes" 7 | "fmt" 8 | "os" 9 | "os/exec" 10 | ) 11 | 12 | func BuildV2Ray() error { 13 | genTestBinaryPath() 14 | if _, err := os.Stat(testBinaryPath); err == nil { 15 | return nil 16 | } 17 | 18 | fmt.Printf("Building V2Ray into path (%s)\n", testBinaryPath) 19 | cmd := exec.Command("go", "build", "-o="+testBinaryPath, GetSourcePath()) 20 | return cmd.Run() 21 | } 22 | 23 | func RunV2RayProtobuf(config []byte) *exec.Cmd { 24 | genTestBinaryPath() 25 | proc := exec.Command(testBinaryPath, "-config=stdin:", "-format=pb") 26 | proc.Stdin = bytes.NewBuffer(config) 27 | proc.Stderr = os.Stderr 28 | proc.Stdout = os.Stdout 29 | 30 | return proc 31 | } 32 | -------------------------------------------------------------------------------- /testing/servers/http/http.go: -------------------------------------------------------------------------------- 1 | package tcp 2 | 3 | import ( 4 | "net/http" 5 | 6 | "v2ray.com/core/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, net.Port(s.Port)), nil 36 | } 37 | 38 | func (s *Server) Close() error { 39 | return s.server.Close() 40 | } 41 | -------------------------------------------------------------------------------- /testing/servers/tcp/port.go: -------------------------------------------------------------------------------- 1 | package tcp 2 | 3 | import ( 4 | "v2ray.com/core/common" 5 | "v2ray.com/core/common/net" 6 | ) 7 | 8 | // PickPort returns an unused TCP port in the system. The port returned is highly likely to be unused, but not guaranteed. 9 | func PickPort() net.Port { 10 | listener, err := net.Listen("tcp4", "127.0.0.1:0") 11 | common.Must(err) 12 | defer listener.Close() 13 | 14 | addr := listener.Addr().(*net.TCPAddr) 15 | return net.Port(addr.Port) 16 | } 17 | -------------------------------------------------------------------------------- /testing/servers/udp/port.go: -------------------------------------------------------------------------------- 1 | package udp 2 | 3 | import ( 4 | "v2ray.com/core/common" 5 | "v2ray.com/core/common/net" 6 | ) 7 | 8 | // PickPort returns an unused UDP port in the system. The port returned is highly likely to be unused, but not guaranteed. 9 | func PickPort() net.Port { 10 | conn, err := net.ListenUDP("udp4", &net.UDPAddr{ 11 | IP: net.LocalHostIP.IP(), 12 | Port: 0, 13 | }) 14 | common.Must(err) 15 | defer conn.Close() 16 | 17 | addr := conn.LocalAddr().(*net.UDPAddr) 18 | return net.Port(addr.Port) 19 | } 20 | -------------------------------------------------------------------------------- /transport/config.go: -------------------------------------------------------------------------------- 1 | package transport 2 | 3 | import ( 4 | "v2ray.com/core/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/config.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package v2ray.core.transport; 4 | option csharp_namespace = "V2Ray.Core.Transport"; 5 | option go_package = "v2ray.com/core/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 | repeated v2ray.core.transport.internet.TransportConfig transport_settings = 1; 15 | } 16 | -------------------------------------------------------------------------------- /transport/internet/connection.go: -------------------------------------------------------------------------------- 1 | package internet 2 | 3 | import ( 4 | "net" 5 | 6 | "v2ray.com/core/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/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 | "v2ray.com/core/common" 10 | "v2ray.com/core/common/net" 11 | "v2ray.com/core/testing/servers/tcp" 12 | . "v2ray.com/core/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/domainsocket/config.go: -------------------------------------------------------------------------------- 1 | // +build !confonly 2 | 3 | package domainsocket 4 | 5 | import ( 6 | "v2ray.com/core/common" 7 | "v2ray.com/core/common/net" 8 | "v2ray.com/core/transport/internet" 9 | ) 10 | 11 | const protocolName = "domainsocket" 12 | const sizeofSunPath = 108 13 | 14 | func (c *Config) GetUnixAddr() (*net.UnixAddr, error) { 15 | path := c.Path 16 | if path == "" { 17 | return nil, newError("empty domain socket path") 18 | } 19 | if c.Abstract && path[0] != '@' { 20 | path = "@" + path 21 | } 22 | if c.Abstract && c.Padding { 23 | raw := []byte(path) 24 | addr := make([]byte, sizeofSunPath) 25 | for i, c := range raw { 26 | addr[i] = c 27 | } 28 | path = string(addr) 29 | } 30 | return &net.UnixAddr{ 31 | Name: path, 32 | Net: "unix", 33 | }, nil 34 | } 35 | 36 | func init() { 37 | common.Must(internet.RegisterProtocolConfigCreator(protocolName, func() interface{} { 38 | return new(Config) 39 | })) 40 | } 41 | -------------------------------------------------------------------------------- /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 = "v2ray.com/core/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 | bool acceptProxyProtocol = 4; 21 | } 22 | -------------------------------------------------------------------------------- /transport/internet/domainsocket/errgen.go: -------------------------------------------------------------------------------- 1 | package domainsocket 2 | 3 | //go:generate go run v2ray.com/core/common/errors/errorgen 4 | -------------------------------------------------------------------------------- /transport/internet/domainsocket/errors.generated.go: -------------------------------------------------------------------------------- 1 | package domainsocket 2 | 3 | import "v2ray.com/core/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 "v2ray.com/core/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/header.go: -------------------------------------------------------------------------------- 1 | package internet 2 | 3 | import ( 4 | "context" 5 | "net" 6 | 7 | "v2ray.com/core/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 | -------------------------------------------------------------------------------- /transport/internet/headers/http/errors.generated.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | import "v2ray.com/core/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/linkedreadRequest.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | import ( 4 | "bufio" 5 | "net/http" 6 | 7 | _ "unsafe" // required to use //go:linkname 8 | ) 9 | 10 | //go:linkname readRequest net/http.readRequest 11 | func readRequest(b *bufio.Reader, deleteHostHeader bool) (req *http.Request, err error) 12 | -------------------------------------------------------------------------------- /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/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 = "v2ray.com/core/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 | -------------------------------------------------------------------------------- /transport/internet/headers/noop/noop.go: -------------------------------------------------------------------------------- 1 | package noop 2 | 3 | import ( 4 | "context" 5 | "net" 6 | 7 | "v2ray.com/core/common" 8 | ) 9 | 10 | type NoOpHeader struct{} 11 | 12 | func (NoOpHeader) Size() int32 { 13 | return 0 14 | } 15 | 16 | // Serialize implements PacketHeader. 17 | func (NoOpHeader) Serialize([]byte) {} 18 | 19 | func NewNoOpHeader(context.Context, interface{}) (interface{}, error) { 20 | return NoOpHeader{}, nil 21 | } 22 | 23 | type NoOpConnectionHeader struct{} 24 | 25 | func (NoOpConnectionHeader) Client(conn net.Conn) net.Conn { 26 | return conn 27 | } 28 | 29 | func (NoOpConnectionHeader) Server(conn net.Conn) net.Conn { 30 | return conn 31 | } 32 | 33 | func NewNoOpConnectionHeader(context.Context, interface{}) (interface{}, error) { 34 | return NoOpConnectionHeader{}, nil 35 | } 36 | 37 | func init() { 38 | common.Must(common.RegisterConfig((*Config)(nil), NewNoOpHeader)) 39 | common.Must(common.RegisterConfig((*ConnectionConfig)(nil), NewNoOpConnectionHeader)) 40 | } 41 | -------------------------------------------------------------------------------- /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 = "v2ray.com/core/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 | -------------------------------------------------------------------------------- /transport/internet/headers/srtp/srtp.go: -------------------------------------------------------------------------------- 1 | package srtp 2 | 3 | import ( 4 | "context" 5 | "encoding/binary" 6 | 7 | "v2ray.com/core/common" 8 | "v2ray.com/core/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 | -------------------------------------------------------------------------------- /transport/internet/headers/srtp/srtp_test.go: -------------------------------------------------------------------------------- 1 | package srtp_test 2 | 3 | import ( 4 | "context" 5 | "testing" 6 | 7 | "v2ray.com/core/common" 8 | "v2ray.com/core/common/buf" 9 | . "v2ray.com/core/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/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 = "v2ray.com/core/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 | -------------------------------------------------------------------------------- /transport/internet/headers/tls/dtls_test.go: -------------------------------------------------------------------------------- 1 | package tls_test 2 | 3 | import ( 4 | "context" 5 | "testing" 6 | 7 | "v2ray.com/core/common" 8 | "v2ray.com/core/common/buf" 9 | . "v2ray.com/core/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/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 = "v2ray.com/core/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/headers/utp/utp.go: -------------------------------------------------------------------------------- 1 | package utp 2 | 3 | import ( 4 | "context" 5 | "encoding/binary" 6 | 7 | "v2ray.com/core/common" 8 | "v2ray.com/core/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 | -------------------------------------------------------------------------------- /transport/internet/headers/utp/utp_test.go: -------------------------------------------------------------------------------- 1 | package utp_test 2 | 3 | import ( 4 | "context" 5 | "testing" 6 | 7 | "v2ray.com/core/common" 8 | "v2ray.com/core/common/buf" 9 | . "v2ray.com/core/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 | -------------------------------------------------------------------------------- /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 = "v2ray.com/core/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/headers/wechat/wechat.go: -------------------------------------------------------------------------------- 1 | package wechat 2 | 3 | import ( 4 | "context" 5 | "encoding/binary" 6 | 7 | "v2ray.com/core/common" 8 | "v2ray.com/core/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 | -------------------------------------------------------------------------------- /transport/internet/headers/wechat/wechat_test.go: -------------------------------------------------------------------------------- 1 | package wechat_test 2 | 3 | import ( 4 | "context" 5 | "testing" 6 | 7 | "v2ray.com/core/common" 8 | "v2ray.com/core/common/buf" 9 | . "v2ray.com/core/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 | -------------------------------------------------------------------------------- /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 = "v2ray.com/core/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/wireguard/wireguard.go: -------------------------------------------------------------------------------- 1 | package wireguard 2 | 3 | import ( 4 | "context" 5 | 6 | "v2ray.com/core/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/internet/http/config.go: -------------------------------------------------------------------------------- 1 | // +build !confonly 2 | 3 | package http 4 | 5 | import ( 6 | "v2ray.com/core/common" 7 | "v2ray.com/core/common/dice" 8 | "v2ray.com/core/transport/internet" 9 | ) 10 | 11 | const protocolName = "http" 12 | 13 | func (c *Config) getHosts() []string { 14 | if len(c.Host) == 0 { 15 | return []string{"www.example.com"} 16 | } 17 | return c.Host 18 | } 19 | 20 | func (c *Config) isValidHost(host string) bool { 21 | hosts := c.getHosts() 22 | for _, h := range hosts { 23 | if h == host { 24 | return true 25 | } 26 | } 27 | return false 28 | } 29 | 30 | func (c *Config) getRandomHost() string { 31 | hosts := c.getHosts() 32 | return hosts[dice.Roll(len(hosts))] 33 | } 34 | 35 | func (c *Config) getNormalizedPath() string { 36 | if c.Path == "" { 37 | return "/" 38 | } 39 | if c.Path[0] != '/' { 40 | return "/" + c.Path 41 | } 42 | return c.Path 43 | } 44 | 45 | func init() { 46 | common.Must(internet.RegisterProtocolConfigCreator(protocolName, func() interface{} { 47 | return new(Config) 48 | })) 49 | } 50 | -------------------------------------------------------------------------------- /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 = "v2ray.com/core/transport/internet/http"; 6 | option java_package = "com.v2ray.core.transport.internet.http"; 7 | option java_multiple_files = true; 8 | 9 | message Config { 10 | repeated string host = 1; 11 | string path = 2; 12 | } 13 | -------------------------------------------------------------------------------- /transport/internet/http/errors.generated.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | import "v2ray.com/core/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/http.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | //go:generate go run v2ray.com/core/common/errors/errorgen 4 | -------------------------------------------------------------------------------- /transport/internet/internet.go: -------------------------------------------------------------------------------- 1 | package internet 2 | 3 | //go:generate go run v2ray.com/core/common/errors/errorgen 4 | -------------------------------------------------------------------------------- /transport/internet/kcp/connection_test.go: -------------------------------------------------------------------------------- 1 | package kcp_test 2 | 3 | import ( 4 | "io" 5 | "testing" 6 | "time" 7 | 8 | "v2ray.com/core/common/buf" 9 | . "v2ray.com/core/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 | -------------------------------------------------------------------------------- /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 | "v2ray.com/core/common" 9 | . "v2ray.com/core/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/kcp/cryptreal.go: -------------------------------------------------------------------------------- 1 | package kcp 2 | 3 | import ( 4 | "crypto/aes" 5 | "crypto/cipher" 6 | "crypto/sha256" 7 | "v2ray.com/core/common" 8 | ) 9 | 10 | func NewAEADAESGCMBasedOnSeed(seed string) cipher.AEAD { 11 | HashedSeed := sha256.Sum256([]byte(seed)) 12 | aesBlock := common.Must2(aes.NewCipher(HashedSeed[:16])).(cipher.Block) 13 | return common.Must2(cipher.NewGCM(aesBlock)).(cipher.AEAD) 14 | } 15 | -------------------------------------------------------------------------------- /transport/internet/kcp/errors.generated.go: -------------------------------------------------------------------------------- 1 | package kcp 2 | 3 | import "v2ray.com/core/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/io_test.go: -------------------------------------------------------------------------------- 1 | package kcp_test 2 | 3 | import ( 4 | "testing" 5 | 6 | . "v2ray.com/core/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 | } 38 | -------------------------------------------------------------------------------- /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 v2ray.com/core/common/errors/errorgen 9 | -------------------------------------------------------------------------------- /transport/internet/kcp/xor.go: -------------------------------------------------------------------------------- 1 | // +build !amd64 2 | 3 | package kcp 4 | 5 | // xorfwd performs XOR forwards in words, x[i] ^= x[i-4], i from 0 to len 6 | func xorfwd(x []byte) { 7 | for i := 4; i < len(x); i++ { 8 | x[i] ^= x[i-4] 9 | } 10 | } 11 | 12 | // xorbkd performs XOR backwords in words, x[i] ^= x[i-4], i from len to 0 13 | func xorbkd(x []byte) { 14 | for i := len(x) - 1; i >= 4; i-- { 15 | x[i] ^= x[i-4] 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 = "v2ray.com/core/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 | -------------------------------------------------------------------------------- /transport/internet/quic/errors.generated.go: -------------------------------------------------------------------------------- 1 | package quic 2 | 3 | import "v2ray.com/core/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/pool.go: -------------------------------------------------------------------------------- 1 | // +build !confonly 2 | 3 | package quic 4 | 5 | import ( 6 | "sync" 7 | 8 | "v2ray.com/core/common/bytespool" 9 | ) 10 | 11 | var pool *sync.Pool 12 | 13 | func init() { 14 | pool = bytespool.GetPool(2048) 15 | } 16 | 17 | func getBuffer() []byte { 18 | return pool.Get().([]byte) 19 | } 20 | 21 | func putBuffer(p []byte) { 22 | pool.Put(p) 23 | } 24 | -------------------------------------------------------------------------------- /transport/internet/quic/quic.go: -------------------------------------------------------------------------------- 1 | // +build !confonly 2 | 3 | package quic 4 | 5 | import ( 6 | "v2ray.com/core/common" 7 | "v2ray.com/core/transport/internet" 8 | ) 9 | 10 | //go:generate go run v2ray.com/core/common/errors/errorgen 11 | 12 | // Here is some modification needs to be done before update quic vendor. 13 | // * use bytespool in buffer_pool.go 14 | // * set MaxReceivePacketSize to 1452 - 32 (16 bytes auth, 16 bytes head) 15 | // 16 | // 17 | 18 | const protocolName = "quic" 19 | const internalDomain = "quic.internal.v2ray.com" 20 | 21 | func init() { 22 | common.Must(internet.RegisterProtocolConfigCreator(protocolName, func() interface{} { 23 | return new(Config) 24 | })) 25 | } 26 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /transport/internet/sockopt_linux_test.go: -------------------------------------------------------------------------------- 1 | package internet_test 2 | 3 | import ( 4 | "context" 5 | "syscall" 6 | "testing" 7 | 8 | "v2ray.com/core/common" 9 | "v2ray.com/core/common/net" 10 | "v2ray.com/core/testing/servers/tcp" 11 | . "v2ray.com/core/transport/internet" 12 | ) 13 | 14 | func TestSockOptMark(t *testing.T) { 15 | t.Skip("requires CAP_NET_ADMIN") 16 | 17 | tcpServer := tcp.Server{ 18 | MsgProcessor: func(b []byte) []byte { 19 | return b 20 | }, 21 | } 22 | dest, err := tcpServer.Start() 23 | common.Must(err) 24 | defer tcpServer.Close() 25 | 26 | const mark = 1 27 | dialer := DefaultSystemDialer{} 28 | conn, err := dialer.Dial(context.Background(), nil, dest, &SocketConfig{Mark: mark}) 29 | common.Must(err) 30 | defer conn.Close() 31 | 32 | rawConn, err := conn.(*net.TCPConn).SyscallConn() 33 | common.Must(err) 34 | err = rawConn.Control(func(fd uintptr) { 35 | m, err := syscall.GetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_MARK) 36 | common.Must(err) 37 | if mark != m { 38 | t.Fatal("unexpected connection mark", m, " want ", mark) 39 | } 40 | }) 41 | common.Must(err) 42 | } 43 | -------------------------------------------------------------------------------- /transport/internet/sockopt_other.go: -------------------------------------------------------------------------------- 1 | // +build js dragonfly netbsd openbsd solaris 2 | 3 | package internet 4 | 5 | func applyOutboundSocketOptions(network string, address string, fd uintptr, config *SocketConfig) error { 6 | return nil 7 | } 8 | 9 | func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig) error { 10 | return nil 11 | } 12 | 13 | func bindAddr(fd uintptr, ip []byte, port uint32) error { 14 | return nil 15 | } 16 | 17 | func setReuseAddr(fd uintptr) error { 18 | return nil 19 | } 20 | 21 | func setReusePort(fd uintptr) error { 22 | return nil 23 | } 24 | -------------------------------------------------------------------------------- /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 | "v2ray.com/core/common" 9 | "v2ray.com/core/common/buf" 10 | "v2ray.com/core/testing/servers/tcp" 11 | . "v2ray.com/core/transport/internet" 12 | ) 13 | 14 | func TestTCPFastOpen(t *testing.T) { 15 | tcpServer := tcp.Server{ 16 | MsgProcessor: func(b []byte) []byte { 17 | return b 18 | }, 19 | } 20 | dest, err := tcpServer.StartContext(context.Background(), &SocketConfig{Tfo: SocketConfig_Enable}) 21 | common.Must(err) 22 | defer tcpServer.Close() 23 | 24 | ctx := context.Background() 25 | dialer := DefaultSystemDialer{} 26 | conn, err := dialer.Dial(ctx, nil, dest, &SocketConfig{ 27 | Tfo: SocketConfig_Enable, 28 | }) 29 | common.Must(err) 30 | defer conn.Close() 31 | 32 | _, err = conn.Write([]byte("abcd")) 33 | common.Must(err) 34 | 35 | b := buf.New() 36 | common.Must2(b.ReadFrom(conn)) 37 | if r := cmp.Diff(b.Bytes(), []byte("abcd")); r != "" { 38 | t.Fatal(r) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /transport/internet/system_listener_test.go: -------------------------------------------------------------------------------- 1 | package internet_test 2 | 3 | import ( 4 | "context" 5 | "net" 6 | "testing" 7 | 8 | "v2ray.com/core/common" 9 | "v2ray.com/core/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 | -------------------------------------------------------------------------------- /transport/internet/tcp/config.go: -------------------------------------------------------------------------------- 1 | // +build !confonly 2 | 3 | package tcp 4 | 5 | import ( 6 | "v2ray.com/core/common" 7 | "v2ray.com/core/transport/internet" 8 | ) 9 | 10 | const protocolName = "tcp" 11 | 12 | func init() { 13 | common.Must(internet.RegisterProtocolConfigCreator(protocolName, func() interface{} { 14 | return new(Config) 15 | })) 16 | } 17 | -------------------------------------------------------------------------------- /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 = "v2ray.com/core/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 | -------------------------------------------------------------------------------- /transport/internet/tcp/errors.generated.go: -------------------------------------------------------------------------------- 1 | package tcp 2 | 3 | import "v2ray.com/core/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/sockopt_freebsd.go: -------------------------------------------------------------------------------- 1 | // +build freebsd 2 | // +build !confonly 3 | 4 | package tcp 5 | 6 | import ( 7 | "v2ray.com/core/common/net" 8 | "v2ray.com/core/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 | -------------------------------------------------------------------------------- /transport/internet/tcp/sockopt_linux_test.go: -------------------------------------------------------------------------------- 1 | // +build linux 2 | 3 | package tcp_test 4 | 5 | import ( 6 | "context" 7 | "strings" 8 | "testing" 9 | 10 | "v2ray.com/core/common" 11 | "v2ray.com/core/testing/servers/tcp" 12 | "v2ray.com/core/transport/internet" 13 | . "v2ray.com/core/transport/internet/tcp" 14 | ) 15 | 16 | func TestGetOriginalDestination(t *testing.T) { 17 | tcpServer := tcp.Server{} 18 | dest, err := tcpServer.Start() 19 | common.Must(err) 20 | defer tcpServer.Close() 21 | 22 | config, err := internet.ToMemoryStreamConfig(nil) 23 | common.Must(err) 24 | conn, err := Dial(context.Background(), dest, config) 25 | common.Must(err) 26 | defer conn.Close() 27 | 28 | originalDest, err := GetOriginalDestination(conn) 29 | if !(dest == originalDest || strings.Contains(err.Error(), "failed to call getsockopt")) { 30 | t.Error("unexpected state") 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /transport/internet/tcp/sockopt_other.go: -------------------------------------------------------------------------------- 1 | // +build !linux,!freebsd 2 | // +build !confonly 3 | 4 | package tcp 5 | 6 | import ( 7 | "v2ray.com/core/common/net" 8 | "v2ray.com/core/transport/internet" 9 | ) 10 | 11 | func GetOriginalDestination(conn internet.Connection) (net.Destination, error) { 12 | return net.Destination{}, nil 13 | } 14 | -------------------------------------------------------------------------------- /transport/internet/tcp/tcp.go: -------------------------------------------------------------------------------- 1 | package tcp 2 | 3 | //go:generate go run v2ray.com/core/common/errors/errorgen 4 | -------------------------------------------------------------------------------- /transport/internet/tls/config_other.go: -------------------------------------------------------------------------------- 1 | // +build !windows 2 | // +build !confonly 3 | 4 | package tls 5 | 6 | import ( 7 | "crypto/x509" 8 | "sync" 9 | ) 10 | 11 | type rootCertsCache struct { 12 | sync.Mutex 13 | pool *x509.CertPool 14 | } 15 | 16 | func (c *rootCertsCache) load() (*x509.CertPool, error) { 17 | c.Lock() 18 | defer c.Unlock() 19 | 20 | if c.pool != nil { 21 | return c.pool, nil 22 | } 23 | 24 | pool, err := x509.SystemCertPool() 25 | if err != nil { 26 | return nil, err 27 | } 28 | c.pool = pool 29 | return pool, nil 30 | } 31 | 32 | var rootCerts rootCertsCache 33 | 34 | func (c *Config) getCertPool() (*x509.CertPool, error) { 35 | if c.DisableSystemRoot { 36 | return c.loadSelfCertPool() 37 | } 38 | 39 | if len(c.Certificate) == 0 { 40 | return rootCerts.load() 41 | } 42 | 43 | pool, err := x509.SystemCertPool() 44 | if err != nil { 45 | return nil, newError("system root").AtWarning().Base(err) 46 | } 47 | for _, cert := range c.Certificate { 48 | if !pool.AppendCertsFromPEM(cert.Certificate) { 49 | return nil, newError("append cert to root").AtWarning().Base(err) 50 | } 51 | } 52 | return pool, err 53 | } 54 | -------------------------------------------------------------------------------- /transport/internet/tls/config_windows.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | // +build !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/tls/errors.generated.go: -------------------------------------------------------------------------------- 1 | package tls 2 | 3 | import "v2ray.com/core/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/config.go: -------------------------------------------------------------------------------- 1 | package udp 2 | 3 | import ( 4 | "v2ray.com/core/common" 5 | "v2ray.com/core/transport/internet" 6 | ) 7 | 8 | func init() { 9 | common.Must(internet.RegisterProtocolConfigCreator(protocolName, func() interface{} { 10 | return new(Config) 11 | })) 12 | } 13 | -------------------------------------------------------------------------------- /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 = "v2ray.com/core/transport/internet/udp"; 6 | option java_package = "com.v2ray.core.transport.internet.udp"; 7 | option java_multiple_files = true; 8 | 9 | message Config {} 10 | -------------------------------------------------------------------------------- /transport/internet/udp/dialer.go: -------------------------------------------------------------------------------- 1 | package udp 2 | 3 | import ( 4 | "context" 5 | 6 | "v2ray.com/core/common" 7 | "v2ray.com/core/common/net" 8 | "v2ray.com/core/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/udp/errors.generated.go: -------------------------------------------------------------------------------- 1 | package udp 2 | 3 | import "v2ray.com/core/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/hub_freebsd.go: -------------------------------------------------------------------------------- 1 | // +build freebsd 2 | 3 | package udp 4 | 5 | import ( 6 | "bytes" 7 | "encoding/gob" 8 | "io" 9 | 10 | "v2ray.com/core/common/net" 11 | "v2ray.com/core/transport/internet" 12 | ) 13 | 14 | // RetrieveOriginalDest from stored laddr, caddr 15 | func RetrieveOriginalDest(oob []byte) net.Destination { 16 | dec := gob.NewDecoder(bytes.NewBuffer(oob)) 17 | var la, ra net.UDPAddr 18 | dec.Decode(&la) 19 | dec.Decode(&ra) 20 | ip, port, err := internet.OriginalDst(&la, &ra) 21 | if err != nil { 22 | return net.Destination{} 23 | } 24 | return net.UDPDestination(net.IPAddress(ip), net.Port(port)) 25 | } 26 | 27 | // ReadUDPMsg stores laddr, caddr for later use 28 | func ReadUDPMsg(conn *net.UDPConn, payload []byte, oob []byte) (int, int, int, *net.UDPAddr, error) { 29 | nBytes, addr, err := conn.ReadFromUDP(payload) 30 | var buf bytes.Buffer 31 | enc := gob.NewEncoder(&buf) 32 | enc.Encode(conn.LocalAddr().(*net.UDPAddr)) 33 | enc.Encode(addr) 34 | var reader io.Reader = &buf 35 | noob, _ := reader.Read(oob) 36 | return nBytes, noob, 0, addr, err 37 | } 38 | -------------------------------------------------------------------------------- /transport/internet/udp/hub_linux.go: -------------------------------------------------------------------------------- 1 | // +build linux 2 | 3 | package udp 4 | 5 | import ( 6 | "syscall" 7 | 8 | "golang.org/x/sys/unix" 9 | "v2ray.com/core/common/net" 10 | ) 11 | 12 | func RetrieveOriginalDest(oob []byte) net.Destination { 13 | msgs, err := syscall.ParseSocketControlMessage(oob) 14 | if err != nil { 15 | return net.Destination{} 16 | } 17 | for _, msg := range msgs { 18 | if msg.Header.Level == syscall.SOL_IP && msg.Header.Type == syscall.IP_RECVORIGDSTADDR { 19 | ip := net.IPAddress(msg.Data[4:8]) 20 | port := net.PortFromBytes(msg.Data[2:4]) 21 | return net.UDPDestination(ip, port) 22 | } else if msg.Header.Level == syscall.SOL_IPV6 && msg.Header.Type == unix.IPV6_RECVORIGDSTADDR { 23 | ip := net.IPAddress(msg.Data[8:24]) 24 | port := net.PortFromBytes(msg.Data[2:4]) 25 | return net.UDPDestination(ip, port) 26 | } 27 | } 28 | return net.Destination{} 29 | } 30 | 31 | func ReadUDPMsg(conn *net.UDPConn, payload []byte, oob []byte) (int, int, int, *net.UDPAddr, error) { 32 | return conn.ReadMsgUDP(payload, oob) 33 | } 34 | -------------------------------------------------------------------------------- /transport/internet/udp/hub_other.go: -------------------------------------------------------------------------------- 1 | // +build !linux,!freebsd 2 | 3 | package udp 4 | 5 | import ( 6 | "v2ray.com/core/common/net" 7 | ) 8 | 9 | func RetrieveOriginalDest(oob []byte) net.Destination { 10 | return net.Destination{} 11 | } 12 | 13 | func ReadUDPMsg(conn *net.UDPConn, payload []byte, oob []byte) (int, int, int, *net.UDPAddr, error) { 14 | nBytes, addr, err := conn.ReadFromUDP(payload) 15 | return nBytes, 0, 0, addr, err 16 | } 17 | -------------------------------------------------------------------------------- /transport/internet/udp/udp.go: -------------------------------------------------------------------------------- 1 | package udp 2 | 3 | //go:generate go run v2ray.com/core/common/errors/errorgen 4 | 5 | const protocolName = "udp" 6 | -------------------------------------------------------------------------------- /transport/internet/websocket/config.go: -------------------------------------------------------------------------------- 1 | // +build !confonly 2 | 3 | package websocket 4 | 5 | import ( 6 | "net/http" 7 | 8 | "v2ray.com/core/common" 9 | "v2ray.com/core/transport/internet" 10 | ) 11 | 12 | const protocolName = "websocket" 13 | 14 | func (c *Config) GetNormalizedPath() string { 15 | path := c.Path 16 | if path == "" { 17 | return "/" 18 | } 19 | if path[0] != '/' { 20 | return "/" + path 21 | } 22 | return path 23 | } 24 | 25 | func (c *Config) GetRequestHeader() http.Header { 26 | header := http.Header{} 27 | for _, h := range c.Header { 28 | header.Add(h.Key, h.Value) 29 | } 30 | return header 31 | } 32 | 33 | func init() { 34 | common.Must(internet.RegisterProtocolConfigCreator(protocolName, func() interface{} { 35 | return new(Config) 36 | })) 37 | } 38 | -------------------------------------------------------------------------------- /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 = "v2ray.com/core/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 | -------------------------------------------------------------------------------- /transport/internet/websocket/errors.generated.go: -------------------------------------------------------------------------------- 1 | package websocket 2 | 3 | import "v2ray.com/core/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 v2ray.com/core/common/errors/errorgen 8 | -------------------------------------------------------------------------------- /transport/internet/xtls/config_other.go: -------------------------------------------------------------------------------- 1 | // +build !windows 2 | // +build !confonly 3 | 4 | package xtls 5 | 6 | import ( 7 | "crypto/x509" 8 | "sync" 9 | ) 10 | 11 | type rootCertsCache struct { 12 | sync.Mutex 13 | pool *x509.CertPool 14 | } 15 | 16 | func (c *rootCertsCache) load() (*x509.CertPool, error) { 17 | c.Lock() 18 | defer c.Unlock() 19 | 20 | if c.pool != nil { 21 | return c.pool, nil 22 | } 23 | 24 | pool, err := x509.SystemCertPool() 25 | if err != nil { 26 | return nil, err 27 | } 28 | c.pool = pool 29 | return pool, nil 30 | } 31 | 32 | var rootCerts rootCertsCache 33 | 34 | func (c *Config) getCertPool() (*x509.CertPool, error) { 35 | if c.DisableSystemRoot { 36 | return c.loadSelfCertPool() 37 | } 38 | 39 | if len(c.Certificate) == 0 { 40 | return rootCerts.load() 41 | } 42 | 43 | pool, err := x509.SystemCertPool() 44 | if err != nil { 45 | return nil, newError("system root").AtWarning().Base(err) 46 | } 47 | for _, cert := range c.Certificate { 48 | if !pool.AppendCertsFromPEM(cert.Certificate) { 49 | return nil, newError("append cert to root").AtWarning().Base(err) 50 | } 51 | } 52 | return pool, err 53 | } 54 | -------------------------------------------------------------------------------- /transport/internet/xtls/config_windows.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | // +build !confonly 3 | 4 | package xtls 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/xtls/errors.generated.go: -------------------------------------------------------------------------------- 1 | package xtls 2 | 3 | import "v2ray.com/core/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/link.go: -------------------------------------------------------------------------------- 1 | package transport 2 | 3 | import "v2ray.com/core/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 | -------------------------------------------------------------------------------- /transport/pipe/reader.go: -------------------------------------------------------------------------------- 1 | package pipe 2 | 3 | import ( 4 | "time" 5 | 6 | "v2ray.com/core/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 | -------------------------------------------------------------------------------- /transport/pipe/writer.go: -------------------------------------------------------------------------------- 1 | package pipe 2 | 3 | import ( 4 | "v2ray.com/core/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 | --------------------------------------------------------------------------------