v2ray源码阅读
创始人
2024-05-29 05:23:49
0

v2ray 项目学习

我发现自己用go语言写了这个久,没有高级的语言应用,只会用基础的用法进行CRUD。v2ray是一个go语言项目,所以希望借这个项目,来提高自己的go语言编程能力。

Interface定义

  1. common/interfaces.go中,定义了一些interface
Closable
Interruptible
Runnable 含(Closable)
HasType
  1. feature/feature.go 定义了feature interface
type Feature interface {common.HasTypecommon.Runnable
}

启动流程

  1. v2ary.go
  • 定义 Server interface,继承Runnable interface
  • 定义Instance,实现Server的start()和close()方法
type Closable interface {// Close release all resources used by this object, including goroutines.Close() error
}type Runnable interface {// Start starts the runnable object. Upon the method returning nil, the object begins to function properly.Start() errorClosable
}type Server interface {common.Runnable
}// Instance combines all functionalities in V2Ray.
type Instance struct {access             sync.Mutex // 锁features           []features.Feature // instance的功能featureResolutions []resolutionrunning            bool // 运行状态ctx context.Context
}
  1. 初始化Instance:main/main.go:main()->main/main.go:startV2Ray()->v2ary.go:New()方法
// main/main.go
func main() {flag.Parse()printVersion()if *version {return}server, err := startV2Ray()if err != nil {fmt.Println(err)// Configuration error. Exit with a special value to prevent systemd from restarting.os.Exit(23)}if *test {fmt.Println("Configuration OK.")os.Exit(0)}if err := server.Start(); err != nil {fmt.Println("Failed to start", err)os.Exit(-1)}defer server.Close()// Explicitly triggering GC to remove garbage from config loading.runtime.GC(){osSignals := make(chan os.Signal, 1)signal.Notify(osSignals, os.Interrupt, syscall.SIGTERM)<-osSignals}
}func startV2Ray() (core.Server, error) {configFiles, err := getConfigFilePath()if err != nil {return nil, err}config, err := core.LoadConfig(GetConfigFormat(), configFiles[0], configFiles)if err != nil {return nil, newError("failed to read config files: [", configFiles.String(), "]").Base(err)}server, err := core.New(config)if err != nil {return nil, newError("failed to create server").Base(err)}return server, nil
}// v2ray.go
func New(config *Config) (*Instance, error) {var server = &Instance{ctx: context.Background()}err, done := initInstanceWithConfig(config, server)if done {return nil, err}return server, nil
}

配置读取

  1. main/main.go:startV2Ray()方法中,如下行读取配置
	config, err := core.LoadConfig(GetConfigFormat(), configFiles[0], configFiles)
  1. 假设读取的是json格式的配置,main/json/config_json.go中,会读取json,关键看serial.LoadJSONConfig(v)这行,他首先会解析json配置到infra/conf/v2ray.go定义的结构体
type Config struct {Port            uint16                 `json:"port"` // Port of this Point server. Deprecated.LogConfig       *LogConfig             `json:"log"`RouterConfig    *RouterConfig          `json:"routing"`DNSConfig       *DnsConfig             `json:"dns"`InboundConfigs  []InboundDetourConfig  `json:"inbounds"`OutboundConfigs []OutboundDetourConfig `json:"outbounds"`InboundConfig   *InboundDetourConfig   `json:"inbound"`        // Deprecated.OutboundConfig  *OutboundDetourConfig  `json:"outbound"`       // Deprecated.InboundDetours  []InboundDetourConfig  `json:"inboundDetour"`  // Deprecated.OutboundDetours []OutboundDetourConfig `json:"outboundDetour"` // Deprecated.Transport       *TransportConfig       `json:"transport"`Policy          *PolicyConfig          `json:"policy"`Api             *ApiConfig             `json:"api"`Stats           *StatsConfig           `json:"stats"`Reverse         *ReverseConfig         `json:"reverse"`
}

然后会调用jsonConfig.Build(),转化为如下pb格式的结构体。
config.pb.go定义的配置,供V2Ray运行使用。

// Config is the master config of V2Ray. V2Ray takes this config as input and
// functions accordingly.
type Config struct {state         protoimpl.MessageStatesizeCache     protoimpl.SizeCacheunknownFields protoimpl.UnknownFields// Inbound handler configurations. Must have at least one item.Inbound []*InboundHandlerConfig `protobuf:"bytes,1,rep,name=inbound,proto3" json:"inbound,omitempty"`// Outbound handler configurations. Must have at least one item. The first// item is used as default for routing.Outbound []*OutboundHandlerConfig `protobuf:"bytes,2,rep,name=outbound,proto3" json:"outbound,omitempty"`// App is for configurations of all features in V2Ray. A feature must// implement the Feature interface, and its config type must be registered// through common.RegisterConfig.App []*serial.TypedMessage `protobuf:"bytes,4,rep,name=app,proto3" json:"app,omitempty"`// Transport settings.// Deprecated. Each inbound and outbound should choose their own transport// config. Date to remove: 2020-01-13//// Deprecated: Do not use.Transport *transport.Config `protobuf:"bytes,5,opt,name=transport,proto3" json:"transport,omitempty"`// Configuration for extensions. The config may not work if corresponding// extension is not loaded into V2Ray. V2Ray will ignore such config during// initialization.Extension []*serial.TypedMessage `protobuf:"bytes,6,rep,name=extension,proto3" json:"extension,omitempty"`
}

V2Ray Instance运行

  1. Config.App是feature配置,从下面代码中,可看出最重要的四个feature分别是:dns、policy、routing、stats
func initInstanceWithConfig(config *Config, server *Instance) (error, bool) {...essentialFeatures := []struct {Type     interface{}Instance features.Feature}{{dns.ClientType(), localdns.New()},{policy.ManagerType(), policy.DefaultManager{}},{routing.RouterType(), routing.DefaultRouter{}},{stats.ManagerType(), stats.NoopManager{}},}for _, f := range essentialFeatures {if server.GetFeature(f.Type) == nil {if err := server.AddFeature(f.Instance); err != nil {return err, true}}}...
}
  1. Instance的feature中inbound.Manager类型feature,里面存储了inboundHandler(虽染inboundHandler被包含在一个feature中,但其实他也算是一个feature)
  2. server.Start()相当于Instance.Start(),其实就相当于Instance.features.start()
func (s *Instance) Start() error {s.access.Lock()defer s.access.Unlock()s.running = truefor _, f := range s.features {if err := f.Start(); err != nil {return err}}newError("V2Ray ", Version(), " started").AtWarning().WriteToLog()return nil
}

Features

InboundHandlerManager、OutboundHandlerManager接口定义

  1. features/inbound/inbound.go:Manager, 暂称作InboundHandlerManager,
type Handler interface {common.RunnableTag() string
}type Manager interface {features.FeatureGetHandler(ctx context.Context, tag string) (Handler, error)AddHandler(ctx context.Context, handler Handler) errorRemoveHandler(ctx context.Context, tag string) error
}func ManagerType() interface{} {return (*Manager)(nil)
}
  1. features/outbound/outbound.go:Manager, 暂称作OutboundHandlerManager,相比于InboundHandlerManager,OutboundHandlerManager的handler多一个Dispatch方法
type Handler interface {common.RunnableTag() stringDispatch(ctx context.Context, link *transport.Link)
}type HandlerSelector interface {Select([]string) []string
}type Manager interface {features.FeatureGetHandler(tag string) HandlerGetDefaultHandler() HandlerAddHandler(ctx context.Context, handler Handler) errorRemoveHandler(ctx context.Context, tag string) error
}func ManagerType() interface{} {return (*Manager)(nil)
}

InboundHandlerManager、OutboundHandlerManager接口实现

  1. app/proxyman/inbound/inbound.go中,实现了InboundHandlerManager,InboundHandlerManager.Start()相当于start所有的untaggedHandler、taggedHandlers
// Manager is to manage all inbound handlers.
type Manager struct {access          sync.RWMutexuntaggedHandler []inbound.HandlertaggedHandlers  map[string]inbound.Handlerrunning         bool
}...// Start implements common.Runnable.
func (m *Manager) Start() error {m.access.Lock()defer m.access.Unlock()m.running = truefor _, handler := range m.taggedHandlers {if err := handler.Start(); err != nil {return err}}for _, handler := range m.untaggedHandler {if err := handler.Start(); err != nil {return err}}return nil
}

InboundHandler、OutboundHandler接口实现

  1. app/proxyman/inbound/always.go、dynamic.go中,实现了InboundHandler,AlwaysInboundHandler.Start()相当于start所有的worker。todo:dynamic的逻辑不一样
type AlwaysOnInboundHandler struct {proxy   proxy.Inboundworkers []workermux     *mux.Servertag     string
}// Start implements common.Runnable.
func (h *AlwaysOnInboundHandler) Start() error {for _, worker := range h.workers {if err := worker.Start(); err != nil {return err}}return nil
}
  1. app/proxyman/inbound/worker.go中定义了worker interface
type worker interface {Start() errorClose() errorPort() net.PortProxy() proxy.Inbound
}
  1. worker interface有两个实现:tcpWorker、udpWorkder
type tcpWorker struct {address         net.Addressport            net.Portproxy           proxy.Inbound //表示采用的代理协议stream          *internet.MemoryStreamConfigrecvOrigDest    booltag             stringdispatcher      routing.DispatchersniffingConfig  *proxyman.SniffingConfiguplinkCounter   stats.CounterdownlinkCounter stats.Counterhub internet.Listenerctx context.Context
}
  1. proxy.Inbound的定义在proxy/proxy.go,他的底层实现有比如vmess、vless、shadowsocks、trojan
// An Inbound processes inbound connections.
type Inbound interface {// Network returns a list of networks that this inbound supports. Connections with not-supported networks will not be passed into Process().Network() []net.Network// Process processes a connection of given network. If necessary, the Inbound can dispatch the connection to an Outbound.Process(context.Context, net.Network, internet.Connection, routing.Dispatcher) error
}

错误日志

  1. common/errors/errors.go 自定义Error
// Error is an error object with underlying error.
type Error struct {pathObj  interface{}prefix   []interface{}message  []interface{}inner    errorseverity log.Severity
}// New returns a new error object with message formed from given arguments.
func New(msg ...interface{}) *Error {return &Error{message:  msg,severity: log.Severity_Info, // 默认日志级别为info}
}

每个目录下,都有一个newError方法,和一个errPathObjHolder。

func newError(values ...interface{}) *errors.Error {return errors.New(values...).WithPathObj(errPathObjHolder{})
}

相关内容

热门资讯

安卓系统的总体框架,架构与核心... 你有没有想过,你的手机里那个神奇的安卓系统,它到底是怎么运作的呢?今天,就让我带你一探究竟,揭开安卓...
谁的安卓系统好,谁家的安卓系统... 说到安卓系统,这可是个热门话题呢!你有没有想过,这么多安卓手机品牌,哪个的操作系统最让你心动?今天,...
安卓系统信付通,安全无忧的移动... 你知道吗?在安卓手机的世界里,有一个超级好用的支付工具,它就是信付通。今天,就让我带你来全方位了解一...
小米官方系统安卓包,深度解析与... 亲爱的数码爱好者们,你是否曾为手机系统而烦恼?市面上那么多手机品牌,各种操作系统让人眼花缭乱。今天,...
自制安卓手机双系统,自制安卓手... 你有没有想过,自己的手机可以同时运行两个操作系统呢?没错,就是那种安卓手机双系统!听起来是不是很酷?...
小米安卓系统怎么设置,科技前沿... 小米手机的用户们,是不是觉得安卓系统有点复杂,设置起来有点头疼呢?别担心,今天就来手把手教你如何轻松...
点歌系统支持安卓系统么,安卓用... 你有没有想过,在手机上点歌听歌,是不是也能像在KTV里那样随心所欲呢?现在,就让我来告诉你一个超级酷...
原版安卓系统刷机,解锁无限可能 你有没有想过,你的安卓手机其实可以焕然一新?没错,就是那种原汁原味的安卓系统,让你的手机重新找回当初...
欧尚改装安卓系统,打造智能驾驶... 你有没有想过,你的欧尚汽车其实也可以变身成为智能座驾呢?没错,就是那个你每天上下班的伙伴——欧尚,现...
安卓系统最新事件,揭秘最新重大... 你知道吗?最近安卓系统可是发生了一件超级大事件,简直让人兴奋得心跳加速!这不,我就迫不及待地来和你分...
早期电话手表安卓系统,安卓系统... 你有没有想过,小时候那些看似简单的玩具,现在竟然也能玩出花来?比如,早期的电话手表,那时候的功能可真...
安卓老系统手机游戏,安卓老系统... 你有没有发现,那些安卓老系统手机,虽然看起来有点古老,但它们在游戏界可是有着自己独特的魅力呢!想象那...
安卓系统重启还是开关,重启与开... 手机突然卡壳了,是不是又该给安卓系统来个重启大法了?别急,今天就来聊聊这个让人又爱又恨的“安卓系统重...
安卓系统刷入iso,轻松实现个... 你有没有想过,你的安卓手机其实可以像变形金刚一样,换上全新的“皮肤”?没错,就是刷入ISO系统!这可...
安卓机系统无法关机,探究原因与... 最近我的安卓手机怎么啦?总是关机不成功,真是让人头疼啊!这可怎么办呢?别急,让我来帮你分析找出解决这...
安卓什么系统广告最多,揭秘最新... 你有没有发现,每次打开安卓手机,广告就像无处不在的小精灵,跳来跳去,让人眼花缭乱?今天,就让我带你一...
禁止中国使用安卓系统,“安卓系... 你知道吗?最近互联网上掀起了一股热议,那就是关于中国是否应该禁止使用安卓系统的话题。这可不是闹着玩的...
如何分辨ios系统和安卓系统,... 你有没有想过,你的手机里装的是iOS系统还是安卓系统呢?这两种系统各有千秋,但分辨它们其实并不难。今...
如何查询安卓系统版本,安卓系统... 你有没有想过,你的安卓手机里隐藏着一个小秘密——那就是它的系统版本!知道这个秘密,不仅能让你更好地了...
lg电视系统和安卓系统比较,性... 你有没有发现,现在家里的电视已经不再是那个傻乎乎的“大盒子”了?它变得聪明起来,能和你互动,能上网,...