mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-07-03 10:18:42 +00:00
refactor: enforce browserDialers-only usage via dialerProxy tags
Agent-Logs-Url: https://github.com/XTLS/Xray-core/sessions/92209153-115a-4303-8c4e-5825c971881b Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
61c39a2834
commit
1cc7349529
@@ -1080,6 +1080,10 @@ type SocketConfig struct {
|
|||||||
|
|
||||||
// Build implements Buildable.
|
// Build implements Buildable.
|
||||||
func (c *SocketConfig) Build() (*internet.SocketConfig, error) {
|
func (c *SocketConfig) Build() (*internet.SocketConfig, error) {
|
||||||
|
if c.BrowserDialer != "" {
|
||||||
|
return nil, errors.PrintRemovedFeatureError("sockopt.browserDialer", "root browserDialers + sockopt.dialerProxy")
|
||||||
|
}
|
||||||
|
|
||||||
tfo := int32(0) // don't invoke setsockopt() for TFO
|
tfo := int32(0) // don't invoke setsockopt() for TFO
|
||||||
if c.TFO != nil {
|
if c.TFO != nil {
|
||||||
switch v := c.TFO.(type) {
|
switch v := c.TFO.(type) {
|
||||||
@@ -1196,7 +1200,6 @@ func (c *SocketConfig) Build() (*internet.SocketConfig, error) {
|
|||||||
AddressPortStrategy: addressPortStrategy,
|
AddressPortStrategy: addressPortStrategy,
|
||||||
HappyEyeballs: happyEyeballs,
|
HappyEyeballs: happyEyeballs,
|
||||||
TrustedXForwardedFor: c.TrustedXForwardedFor,
|
TrustedXForwardedFor: c.TrustedXForwardedFor,
|
||||||
BrowserDialer: c.BrowserDialer,
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1974,11 +1977,15 @@ func (c *StreamConfig) Build() (*internet.StreamConfig, error) {
|
|||||||
config.ProtocolName = protocol
|
config.ProtocolName = protocol
|
||||||
}
|
}
|
||||||
if c.SocketSettings != nil && c.SocketSettings.BrowserDialer != "" {
|
if c.SocketSettings != nil && c.SocketSettings.BrowserDialer != "" {
|
||||||
|
return nil, errors.PrintRemovedFeatureError("sockopt.browserDialer", "root browserDialers + sockopt.dialerProxy")
|
||||||
|
}
|
||||||
|
if c.SocketSettings != nil && c.SocketSettings.DialerProxy != "" {
|
||||||
|
if _, ok := browser_dialer.GetAddressByTag(c.SocketSettings.DialerProxy); ok {
|
||||||
if config.ProtocolName != "websocket" && config.ProtocolName != "splithttp" {
|
if config.ProtocolName != "websocket" && config.ProtocolName != "splithttp" {
|
||||||
return nil, errors.New("sockopt.browserDialer only supports websocket or splithttp")
|
return nil, errors.New("dialerProxy tag ", c.SocketSettings.DialerProxy, " maps to browserDialers and only supports websocket or splithttp")
|
||||||
}
|
}
|
||||||
if strings.EqualFold(c.Security, "reality") {
|
if strings.EqualFold(c.Security, "reality") {
|
||||||
return nil, errors.New("sockopt.browserDialer does not support REALITY")
|
return nil, errors.New("dialerProxy tag ", c.SocketSettings.DialerProxy, " maps to browserDialers and does not support REALITY")
|
||||||
}
|
}
|
||||||
if config.ProtocolName == "splithttp" {
|
if config.ProtocolName == "splithttp" {
|
||||||
splitHTTPSettings := c.SplitHTTPSettings
|
splitHTTPSettings := c.SplitHTTPSettings
|
||||||
@@ -1989,10 +1996,11 @@ func (c *StreamConfig) Build() (*internet.StreamConfig, error) {
|
|||||||
splitHTTPSettingsCopy := *splitHTTPSettings
|
splitHTTPSettingsCopy := *splitHTTPSettings
|
||||||
hs, err := splitHTTPSettingsCopy.Build()
|
hs, err := splitHTTPSettingsCopy.Build()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("failed to build XHTTP config for browserDialer validation.").Base(err)
|
return nil, errors.New("failed to build XHTTP config for browserDialers validation.").Base(err)
|
||||||
}
|
}
|
||||||
if splitHTTPConfig, ok := hs.(*splithttp.Config); ok && splitHTTPConfig.Mode != "auto" && splitHTTPConfig.Mode != "packet-up" {
|
if splitHTTPConfig, ok := hs.(*splithttp.Config); ok && splitHTTPConfig.Mode != "auto" && splitHTTPConfig.Mode != "packet-up" {
|
||||||
return nil, errors.New("sockopt.browserDialer only supports XHTTP modes \"auto\" or \"packet-up\", got: \"", splitHTTPConfig.Mode, "\"")
|
return nil, errors.New("dialerProxy tag ", c.SocketSettings.DialerProxy, " maps to browserDialers and only supports XHTTP modes \"auto\" or \"packet-up\", got: \"", splitHTTPConfig.Mode, "\"")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2113,9 +2121,6 @@ func (c *StreamConfig) Build() (*internet.StreamConfig, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("Failed to build sockopt.").Base(err)
|
return nil, errors.New("Failed to build sockopt.").Base(err)
|
||||||
}
|
}
|
||||||
if err := browser_dialer.EnsureDialerWithAddress(ss.BrowserDialer); err != nil {
|
|
||||||
return nil, errors.New("Failed to start Browser Dialer listener.").Base(err)
|
|
||||||
}
|
|
||||||
config.SocketSettings = ss
|
config.SocketSettings = ss
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -614,6 +614,9 @@ func (c *Config) Build() (*core.Config, error) {
|
|||||||
if len(c.Transport) > 0 {
|
if len(c.Transport) > 0 {
|
||||||
return nil, errors.PrintRemovedFeatureError("Global transport config", "streamSettings in inbounds and outbounds")
|
return nil, errors.PrintRemovedFeatureError("Global transport config", "streamSettings in inbounds and outbounds")
|
||||||
}
|
}
|
||||||
|
if err := browser_dialer.CheckLegacyEnv(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
browserDialerTags := make(map[string]string, len(c.BrowserDialers))
|
browserDialerTags := make(map[string]string, len(c.BrowserDialers))
|
||||||
for _, browserDialer := range c.BrowserDialers {
|
for _, browserDialer := range c.BrowserDialers {
|
||||||
|
|||||||
@@ -62,8 +62,20 @@ func GetAddressByTag(tag string) (string, bool) {
|
|||||||
return addr, ok
|
return addr, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CheckLegacyEnv() error {
|
||||||
|
envAddress := platform.NewEnvFlag(platform.BrowserDialerAddress).GetValue(func() string { return "" })
|
||||||
|
if envAddress == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return errors.PrintRemovedFeatureError("env "+platform.BrowserDialerAddress, "root browserDialers + sockopt.dialerProxy")
|
||||||
|
}
|
||||||
|
|
||||||
func ConfigureDialerTags(tags map[string]string) error {
|
func ConfigureDialerTags(tags map[string]string) error {
|
||||||
|
if err := CheckLegacyEnv(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
next := make(map[string]string, len(tags))
|
next := make(map[string]string, len(tags))
|
||||||
|
listenAddrByPort := make(map[string]string, len(tags))
|
||||||
for tag, addr := range tags {
|
for tag, addr := range tags {
|
||||||
if tag == "" {
|
if tag == "" {
|
||||||
return errors.New("browserDialers tag cannot be empty")
|
return errors.New("browserDialers tag cannot be empty")
|
||||||
@@ -71,11 +83,36 @@ func ConfigureDialerTags(tags map[string]string) error {
|
|||||||
if addr == "" {
|
if addr == "" {
|
||||||
return errors.New("browserDialers url cannot be empty for tag: ", tag)
|
return errors.New("browserDialers url cannot be empty for tag: ", tag)
|
||||||
}
|
}
|
||||||
if err := EnsureDialerWithAddress(addr); err != nil {
|
listenAddr, _, ok := parseBrowserDialerAddress(addr)
|
||||||
return errors.New("invalid browserDialers entry for tag ", tag).Base(err)
|
if !ok {
|
||||||
|
return errors.New("invalid browserDialers entry for tag ", tag, ": ", addr)
|
||||||
}
|
}
|
||||||
|
_, port, err := net.SplitHostPort(listenAddr)
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("invalid browserDialers listen address for tag ", tag, ": ", listenAddr)
|
||||||
|
}
|
||||||
|
if existingAddr, found := listenAddrByPort[port]; found && existingAddr != listenAddr {
|
||||||
|
return errors.New("browserDialers cannot use the same port with a different listen address: ", existingAddr, " and ", listenAddr)
|
||||||
|
}
|
||||||
|
listenAddrByPort[port] = listenAddr
|
||||||
next[tag] = addr
|
next[tag] = addr
|
||||||
}
|
}
|
||||||
|
mu.RLock()
|
||||||
|
defer mu.RUnlock()
|
||||||
|
for existingAddr := range dialerServers {
|
||||||
|
_, existingPort, splitErr := net.SplitHostPort(existingAddr)
|
||||||
|
if splitErr != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if newAddr, found := listenAddrByPort[existingPort]; found && newAddr != existingAddr {
|
||||||
|
return errors.New("browserDialers cannot use the same port with a different listen address: ", existingAddr, " and ", newAddr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for tag, addr := range next {
|
||||||
|
if err := EnsureDialerWithAddress(addr); err != nil {
|
||||||
|
return errors.New("failed to initialize browserDialers listener for tag ", tag).Base(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
dialerTags = next
|
dialerTags = next
|
||||||
@@ -203,11 +240,11 @@ func closeConnection(w http.ResponseWriter) {
|
|||||||
func getDialerByAddress(addr string) (*dialerInstance, error) {
|
func getDialerByAddress(addr string) (*dialerInstance, error) {
|
||||||
listenAddr, path, ok := parseBrowserDialerAddress(addr)
|
listenAddr, path, ok := parseBrowserDialerAddress(addr)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.New("invalid sockopt.browserDialer: ", addr)
|
return nil, errors.New("invalid browserDialers url: ", addr)
|
||||||
}
|
}
|
||||||
_, port, err := net.SplitHostPort(listenAddr)
|
_, port, err := net.SplitHostPort(listenAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("invalid sockopt.browserDialer listen address: ", listenAddr)
|
return nil, errors.New("invalid browserDialers listen address: ", listenAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
key := listenAddr + path
|
key := listenAddr + path
|
||||||
@@ -230,7 +267,7 @@ func getDialerByAddress(addr string) (*dialerInstance, error) {
|
|||||||
for existingAddr := range dialerServers {
|
for existingAddr := range dialerServers {
|
||||||
_, existingPort, splitErr := net.SplitHostPort(existingAddr)
|
_, existingPort, splitErr := net.SplitHostPort(existingAddr)
|
||||||
if splitErr == nil && existingPort == port {
|
if splitErr == nil && existingPort == port {
|
||||||
return nil, errors.New("sockopt.browserDialer cannot use the same port with a different listen address: ", existingAddr, " and ", listenAddr)
|
return nil, errors.New("browserDialers cannot use the same port with a different listen address: ", existingAddr, " and ", listenAddr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
newServer, serverErr := newDialerServer(listenAddr)
|
newServer, serverErr := newDialerServer(listenAddr)
|
||||||
@@ -353,11 +390,11 @@ func dialTaskWithAddress(addr string, task task) (*websocket.Conn, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if addr == "" {
|
if addr == "" {
|
||||||
return nil, errors.New("browser dialer is not configured; set sockopt.browserDialer")
|
return nil, errors.New("browser dialer is not configured; set root browserDialers and use sockopt.dialerProxy tag")
|
||||||
}
|
}
|
||||||
dialer, err := getDialerByAddress(addr)
|
dialer, err := getDialerByAddress(addr)
|
||||||
if err != nil || dialer == nil {
|
if err != nil || dialer == nil {
|
||||||
return nil, errors.New("browser dialer is not configured for sockopt.browserDialer: ", addr)
|
return nil, errors.New("browser dialer is not configured for browserDialers url: ", addr)
|
||||||
}
|
}
|
||||||
conns := dialer.conns
|
conns := dialer.conns
|
||||||
|
|
||||||
@@ -389,15 +426,3 @@ func CheckOK(conn *websocket.Conn) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func notifyRemovedEnv() {
|
|
||||||
envAddress := platform.NewEnvFlag(platform.BrowserDialerAddress).GetValue(func() string { return "" })
|
|
||||||
if envAddress == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
errors.LogWarning(context.Background(), errors.PrintRemovedFeatureError("env "+platform.BrowserDialerAddress, "sockopt.browserDialer"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
notifyRemovedEnv()
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -63,13 +63,10 @@ func getHTTPClient(ctx context.Context, dest net.Destination, streamSettings *in
|
|||||||
realityConfig := reality.ConfigFromStreamSettings(streamSettings)
|
realityConfig := reality.ConfigFromStreamSettings(streamSettings)
|
||||||
browserDialer := ""
|
browserDialer := ""
|
||||||
if streamSettings.SocketSettings != nil {
|
if streamSettings.SocketSettings != nil {
|
||||||
browserDialer = streamSettings.SocketSettings.BrowserDialer
|
|
||||||
if browserDialer == "" {
|
|
||||||
if taggedDialer, ok := browser_dialer.GetAddressByTag(streamSettings.SocketSettings.DialerProxy); ok {
|
if taggedDialer, ok := browser_dialer.GetAddressByTag(streamSettings.SocketSettings.DialerProxy); ok {
|
||||||
browserDialer = taggedDialer
|
browserDialer = taggedDialer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if browser_dialer.HasBrowserDialerWithAddress(browserDialer) && realityConfig == nil {
|
if browser_dialer.HasBrowserDialerWithAddress(browserDialer) && realityConfig == nil {
|
||||||
transportConfig := streamSettings.ProtocolSettings.(*Config)
|
transportConfig := streamSettings.ProtocolSettings.(*Config)
|
||||||
|
|||||||
@@ -119,13 +119,10 @@ func dialWebSocket(ctx context.Context, dest net.Destination, streamSettings *in
|
|||||||
|
|
||||||
browserDialer := ""
|
browserDialer := ""
|
||||||
if streamSettings.SocketSettings != nil {
|
if streamSettings.SocketSettings != nil {
|
||||||
browserDialer = streamSettings.SocketSettings.BrowserDialer
|
|
||||||
if browserDialer == "" {
|
|
||||||
if taggedDialer, ok := browser_dialer.GetAddressByTag(streamSettings.SocketSettings.DialerProxy); ok {
|
if taggedDialer, ok := browser_dialer.GetAddressByTag(streamSettings.SocketSettings.DialerProxy); ok {
|
||||||
browserDialer = taggedDialer
|
browserDialer = taggedDialer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if browser_dialer.HasBrowserDialerWithAddress(browserDialer) {
|
if browser_dialer.HasBrowserDialerWithAddress(browserDialer) {
|
||||||
conn, err := browser_dialer.DialWSWithAddress(browserDialer, uri, ed)
|
conn, err := browser_dialer.DialWSWithAddress(browserDialer, uri, ed)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user