Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Riverrun TCP Stream Modifier into V2Ray #2946

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 3 additions & 3 deletions go.mod
@@ -1,8 +1,6 @@
module github.com/v2fly/v2ray-core/v5

go 1.21

toolchain go1.21.4
go 1.21.7

require (
github.com/adrg/xdg v0.4.0
Expand All @@ -27,6 +25,7 @@ require (
github.com/stretchr/testify v1.8.4
github.com/v2fly/BrowserBridge v0.0.0-20210430233438-0570fc1d7d08
github.com/v2fly/VSign v0.0.0-20201108000810-e2adc24bf848
github.com/v2fly/riverrun v0.0.0-20240322144348-1f041445f73f
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e
github.com/vincent-petithory/dataurl v1.0.0
github.com/xiaokangwang/VLite v0.0.0-20220418190619-cff95160a432
Expand All @@ -52,6 +51,7 @@ require (
github.com/bufbuild/protocompile v0.8.0 // indirect
github.com/cloudflare/circl v1.3.7 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dchest/siphash v1.2.3 // indirect
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 // indirect
github.com/ebfe/bcrypt_pbkdf v0.0.0-20140212075826-3c8d2dcb253a // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Expand Up @@ -53,6 +53,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsr
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dchest/siphash v1.2.3 h1:QXwFc8cFOR2dSa/gE6o/HokBMWtLUaNDVd+22aKHeEA=
github.com/dchest/siphash v1.2.3/go.mod h1:0NvQU092bT0ipiFN++/rXm69QG9tVxLAlQHIXMPAkHc=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-metro v0.0.0-20180109044635-280f6062b5bc/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw=
github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw=
Expand Down Expand Up @@ -322,6 +324,8 @@ github.com/v2fly/BrowserBridge v0.0.0-20210430233438-0570fc1d7d08 h1:4Yh46CVE3k/
github.com/v2fly/BrowserBridge v0.0.0-20210430233438-0570fc1d7d08/go.mod h1:KAuQNm+LWQCOFqdBcUgihPzRpVXRKzGbTNhfEfRZ4wY=
github.com/v2fly/VSign v0.0.0-20201108000810-e2adc24bf848 h1:p1UzXK6VAutXFFQMnre66h7g1BjRKUnLv0HfmmRoz7w=
github.com/v2fly/VSign v0.0.0-20201108000810-e2adc24bf848/go.mod h1:p80Bv154ZtrGpXMN15slDCqc9UGmfBuUzheDFBYaW/M=
github.com/v2fly/riverrun v0.0.0-20240322144348-1f041445f73f h1:iLZduIN4zpD2a1fYGZBCpyT2+HK8icbcanY6gIOcnKg=
github.com/v2fly/riverrun v0.0.0-20240322144348-1f041445f73f/go.mod h1:2N9yEQTlHeGrjdpbDi3+RBq/pUf2LdSiOwbgNyva4VI=
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e h1:5QefA066A1tF8gHIiADmOVOV5LS43gt3ONnlEl3xkwI=
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e/go.mod h1:5t19P9LBIrNamL6AcMQOncg/r10y3Pc01AbHeMhwlpU=
github.com/vincent-petithory/dataurl v1.0.0 h1:cXw+kPto8NLuJtlMsI152irrVw9fRDX8AbShPRpg2CI=
Expand Down
3 changes: 3 additions & 0 deletions main/distro/all/all.go
Expand Up @@ -87,6 +87,9 @@ import (
_ "github.com/v2fly/v2ray-core/v5/transport/internet/headers/wechat"
_ "github.com/v2fly/v2ray-core/v5/transport/internet/headers/wireguard"

// Engineering Transport Headers
_ "github.com/v2fly/v2ray-core/v5/transport/internet/headers/riverrun"

// Geo loaders
_ "github.com/v2fly/v2ray-core/v5/infra/conf/geodata/memconservative"
_ "github.com/v2fly/v2ray-core/v5/infra/conf/geodata/standard"
Expand Down
150 changes: 150 additions & 0 deletions transport/internet/headers/riverrun/config.pb.go
@@ -0,0 +1,150 @@
package riverrun

import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)

const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)

type Config struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields

Seed string `protobuf:"bytes,4,opt,name=seed,proto3" json:"seed,omitempty"`
}

func (x *Config) Reset() {
*x = Config{}
if protoimpl.UnsafeEnabled {
mi := &file_transport_internet_headers_riverrun_config_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}

func (x *Config) String() string {
return protoimpl.X.MessageStringOf(x)
}

func (*Config) ProtoMessage() {}

func (x *Config) ProtoReflect() protoreflect.Message {
mi := &file_transport_internet_headers_riverrun_config_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}

// Deprecated: Use Config.ProtoReflect.Descriptor instead.
func (*Config) Descriptor() ([]byte, []int) {
return file_transport_internet_headers_riverrun_config_proto_rawDescGZIP(), []int{0}
}

func (x *Config) GetSeed() string {
if x != nil {
return x.Seed
}
return ""
}

var File_transport_internet_headers_riverrun_config_proto protoreflect.FileDescriptor

var file_transport_internet_headers_riverrun_config_proto_rawDesc = []byte{
0x0a, 0x30, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65,
0x72, 0x6e, 0x65, 0x74, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x2f, 0x72, 0x69, 0x76,
0x65, 0x72, 0x72, 0x75, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x12, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x74,
0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
0x74, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x2e, 0x72, 0x69, 0x76, 0x65, 0x72, 0x72,
0x75, 0x6e, 0x22, 0x1c, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04,
0x73, 0x65, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x65, 0x65, 0x64,
0x42, 0xab, 0x01, 0x0a, 0x32, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63,
0x6f, 0x72, 0x65, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e,
0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x2e, 0x72,
0x69, 0x76, 0x65, 0x72, 0x72, 0x75, 0x6e, 0x50, 0x01, 0x5a, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75,
0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61,
0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70,
0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2f, 0x68, 0x65, 0x61,
0x64, 0x65, 0x72, 0x73, 0x2f, 0x72, 0x69, 0x76, 0x65, 0x72, 0x72, 0x75, 0x6e, 0xaa, 0x02, 0x2e,
0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73,
0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x48, 0x65,
0x61, 0x64, 0x65, 0x72, 0x73, 0x2e, 0x52, 0x69, 0x76, 0x65, 0x72, 0x72, 0x75, 0x6e, 0x62, 0x06,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}

var (
file_transport_internet_headers_riverrun_config_proto_rawDescOnce sync.Once
file_transport_internet_headers_riverrun_config_proto_rawDescData = file_transport_internet_headers_riverrun_config_proto_rawDesc
)

func file_transport_internet_headers_riverrun_config_proto_rawDescGZIP() []byte {
file_transport_internet_headers_riverrun_config_proto_rawDescOnce.Do(func() {
file_transport_internet_headers_riverrun_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_transport_internet_headers_riverrun_config_proto_rawDescData)
})
return file_transport_internet_headers_riverrun_config_proto_rawDescData
}

var file_transport_internet_headers_riverrun_config_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_transport_internet_headers_riverrun_config_proto_goTypes = []interface{}{
(*Config)(nil), // 0: v2ray.core.transport.internet.headers.riverrun.Config
}
var file_transport_internet_headers_riverrun_config_proto_depIdxs = []int32{
0, // [0:0] is the sub-list for method output_type
0, // [0:0] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}

func init() { file_transport_internet_headers_riverrun_config_proto_init() }
func file_transport_internet_headers_riverrun_config_proto_init() {
if File_transport_internet_headers_riverrun_config_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_transport_internet_headers_riverrun_config_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Config); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_transport_internet_headers_riverrun_config_proto_rawDesc,
NumEnums: 0,
NumMessages: 1,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_transport_internet_headers_riverrun_config_proto_goTypes,
DependencyIndexes: file_transport_internet_headers_riverrun_config_proto_depIdxs,
MessageInfos: file_transport_internet_headers_riverrun_config_proto_msgTypes,
}.Build()
File_transport_internet_headers_riverrun_config_proto = out.File
file_transport_internet_headers_riverrun_config_proto_rawDesc = nil
file_transport_internet_headers_riverrun_config_proto_goTypes = nil
file_transport_internet_headers_riverrun_config_proto_depIdxs = nil
}
11 changes: 11 additions & 0 deletions transport/internet/headers/riverrun/config.proto
@@ -0,0 +1,11 @@
syntax = "proto3";

package v2ray.core.transport.internet.headers.riverrun;
option csharp_namespace = "V2Ray.Core.Transport.Internet.Headers.Riverrun";
option go_package = "github.com/v2fly/v2ray-core/v5/transport/internet/headers/riverrun";
option java_package = "com.v2ray.core.transport.internet.headers.riverrun";
option java_multiple_files = true;

message Config {
string seed = 4;
}
9 changes: 9 additions & 0 deletions transport/internet/headers/riverrun/errors.generated.go
@@ -0,0 +1,9 @@
package riverrun

import "github.com/v2fly/v2ray-core/v5/common/errors"

type errPathObjHolder struct{}

func newError(values ...interface{}) *errors.Error {
return errors.New(values...).WithPathObj(errPathObjHolder{})
}
101 changes: 101 additions & 0 deletions transport/internet/headers/riverrun/riverrun.go
@@ -0,0 +1,101 @@
package riverrun

import (
"context"
"fmt"
gonet "net"
"time"

"github.com/v2fly/riverrun"
"github.com/v2fly/riverrun/common/drbg"

"github.com/v2fly/v2ray-core/v5/common"
"github.com/v2fly/v2ray-core/v5/common/net"
"github.com/v2fly/v2ray-core/v5/transport/internet"
)

//go:generate go run github.com/v2fly/v2ray-core/v5/common/errors/errorgen

type errConn struct {
err error
}

func (e errConn) Read(b []byte) (n int, err error) {
return 0, e.err
}

func (e errConn) Write(b []byte) (n int, err error) {
return 0, e.err
}

func (e errConn) Close() error {
return e.err
}

func (e errConn) LocalAddr() gonet.Addr {
return &gonet.UnixAddr{Name: "error"}
}

func (e errConn) RemoteAddr() gonet.Addr {
return &gonet.UnixAddr{Name: "error"}
}

func (e errConn) SetDeadline(t time.Time) error {
return e.err
}

func (e errConn) SetReadDeadline(t time.Time) error {
return e.err
}

func (e errConn) SetWriteDeadline(t time.Time) error {
return e.err
}

type riverrunConnectionFactory struct {
config *Config
}

func (p riverrunConnectionFactory) Infof(format string, a ...interface{}) {
newError(fmt.Sprintf(format, a...)).AtInfo().WriteToLog()
}

func (p riverrunConnectionFactory) Debugf(format string, a ...interface{}) {
newError(fmt.Sprintf(format, a...)).AtDebug().WriteToLog()
}

func (p riverrunConnectionFactory) Client(conn net.Conn) net.Conn {
seed, err := drbg.SeedFromBytes([]byte(p.config.Seed))
if err != nil {
return errConn{err: err}
}
wconn, err := riverrun.NewConn(conn, false, seed, p)
if err != nil {
return errConn{err: err}
}
return wconn
}

func (p riverrunConnectionFactory) Server(conn net.Conn) net.Conn {
seed, err := drbg.SeedFromBytes([]byte(p.config.Seed))
if err != nil {
return errConn{err: err}
}
wconn, err := riverrun.NewConn(conn, true, seed, p)
if err != nil {
return errConn{err: err}
}
return wconn
}

func newRiverrunConnectionAuthenticator(config *Config) (internet.ConnectionAuthenticator, error) {

Check failure on line 91 in transport/internet/headers/riverrun/riverrun.go

View workflow job for this annotation

GitHub Actions / lint

newRiverrunConnectionAuthenticator - result 1 (error) is always nil (unparam)
return riverrunConnectionFactory{
config: config,
}, nil
}

func init() {
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
return newRiverrunConnectionAuthenticator(config.(*Config))
}))
}