mirror of
https://github.com/openlibrecommunity/olcrtc.git
synced 2026-05-26 07:08:11 +00:00
feat(server): add username/password auth for outbound SOCKS5 proxy (RFC 1929)
This commit is contained in:
@@ -189,6 +189,8 @@ type Config struct {
|
||||
DNSServer string
|
||||
SOCKSProxyAddr string
|
||||
SOCKSProxyPort int
|
||||
SOCKSProxyUser string
|
||||
SOCKSProxyPass string
|
||||
Video VideoConfig
|
||||
VP8 VP8Config
|
||||
SEI SEIConfig
|
||||
@@ -652,6 +654,8 @@ func runOnce(
|
||||
DNSServer: cfg.DNSServer,
|
||||
SOCKSProxyAddr: cfg.SOCKSProxyAddr,
|
||||
SOCKSProxyPort: cfg.SOCKSProxyPort,
|
||||
SOCKSProxyUser: cfg.SOCKSProxyUser,
|
||||
SOCKSProxyPass: cfg.SOCKSProxyPass,
|
||||
TransportOptions: opts,
|
||||
Engine: cfg.Engine,
|
||||
URL: cfg.URL,
|
||||
|
||||
@@ -108,6 +108,8 @@ type SOCKS struct {
|
||||
Pass string `yaml:"pass"`
|
||||
ProxyAddr string `yaml:"proxy_addr"`
|
||||
ProxyPort int `yaml:"proxy_port"`
|
||||
ProxyUser string `yaml:"proxy_user"`
|
||||
ProxyPass string `yaml:"proxy_pass"`
|
||||
}
|
||||
|
||||
// Engine selects a direct SFU connection when Auth.Provider is "none".
|
||||
@@ -262,6 +264,8 @@ func Apply(dst session.Config, f File) session.Config {
|
||||
dst.DNSServer = pickString(dst.DNSServer, f.Net.DNS)
|
||||
dst.SOCKSProxyAddr = pickString(dst.SOCKSProxyAddr, f.SOCKS.ProxyAddr)
|
||||
dst.SOCKSProxyPort = pickInt(dst.SOCKSProxyPort, f.SOCKS.ProxyPort)
|
||||
dst.SOCKSProxyUser = pickString(dst.SOCKSProxyUser, f.SOCKS.ProxyUser)
|
||||
dst.SOCKSProxyPass = pickString(dst.SOCKSProxyPass, f.SOCKS.ProxyPass)
|
||||
dst.Video.Width = pickInt(dst.Video.Width, f.Video.Width)
|
||||
dst.Video.Height = pickInt(dst.Video.Height, f.Video.Height)
|
||||
dst.Video.FPS = pickInt(dst.Video.FPS, f.Video.FPS)
|
||||
@@ -307,6 +311,8 @@ func ApplyProfile(base session.Config, p Profile) session.Config {
|
||||
dst.DNSServer = overlayString(dst.DNSServer, p.Net.DNS)
|
||||
dst.SOCKSProxyAddr = overlayString(dst.SOCKSProxyAddr, p.SOCKS.ProxyAddr)
|
||||
dst.SOCKSProxyPort = overlayInt(dst.SOCKSProxyPort, p.SOCKS.ProxyPort)
|
||||
dst.SOCKSProxyUser = overlayString(dst.SOCKSProxyUser, p.SOCKS.ProxyUser)
|
||||
dst.SOCKSProxyPass = overlayString(dst.SOCKSProxyPass, p.SOCKS.ProxyPass)
|
||||
dst.Video.Width = overlayInt(dst.Video.Width, p.Video.Width)
|
||||
dst.Video.Height = overlayInt(dst.Video.Height, p.Video.Height)
|
||||
dst.Video.FPS = overlayInt(dst.Video.FPS, p.Video.FPS)
|
||||
|
||||
@@ -77,6 +77,8 @@ type Server struct {
|
||||
resolver *net.Resolver
|
||||
socksProxyAddr string
|
||||
socksProxyPort int
|
||||
socksProxyUser string
|
||||
socksProxyPass string
|
||||
liveness control.Config
|
||||
health *runtime.HealthTracker
|
||||
done chan struct{}
|
||||
@@ -110,6 +112,8 @@ type Config struct {
|
||||
DNSServer string
|
||||
SOCKSProxyAddr string
|
||||
SOCKSProxyPort int
|
||||
SOCKSProxyUser string
|
||||
SOCKSProxyPass string
|
||||
TransportOptions transport.Options
|
||||
Engine string
|
||||
URL string
|
||||
@@ -166,6 +170,8 @@ func Run(ctx context.Context, cfg Config) error {
|
||||
dnsServer: cfg.DNSServer,
|
||||
socksProxyAddr: cfg.SOCKSProxyAddr,
|
||||
socksProxyPort: cfg.SOCKSProxyPort,
|
||||
socksProxyUser: cfg.SOCKSProxyUser,
|
||||
socksProxyPass: cfg.SOCKSProxyPass,
|
||||
liveness: cfg.Liveness,
|
||||
health: runtime.NewHealthTracker(cfg.OnHealth),
|
||||
peerSessions: make(map[string]*peerSession),
|
||||
@@ -914,15 +920,55 @@ func (s *Server) dial(req ConnectRequest) (net.Conn, error) {
|
||||
}
|
||||
|
||||
func (s *Server) socks5Connect(conn net.Conn, targetAddr string, targetPort int) error {
|
||||
if s.socksProxyUser != "" {
|
||||
// Offer username/password auth (RFC 1929) only.
|
||||
if _, err := conn.Write([]byte{5, 1, 2}); err != nil {
|
||||
return fmt.Errorf("failed to write socks5 auth: %w", err)
|
||||
}
|
||||
} else {
|
||||
// No authentication.
|
||||
if _, err := conn.Write([]byte{5, 1, 0}); err != nil {
|
||||
return fmt.Errorf("failed to write socks5 auth: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
resp := make([]byte, 2)
|
||||
if _, err := io.ReadFull(conn, resp); err != nil {
|
||||
return fmt.Errorf("failed to read socks5 auth resp: %w", err)
|
||||
}
|
||||
if resp[0] != 5 || resp[1] != 0 {
|
||||
if resp[0] != 5 {
|
||||
return ErrSocks5AuthFailed
|
||||
}
|
||||
switch resp[1] {
|
||||
case 0: // no auth accepted
|
||||
if s.socksProxyUser != "" {
|
||||
return ErrSocks5AuthFailed
|
||||
}
|
||||
case 2: // username/password
|
||||
user := s.socksProxyUser
|
||||
pass := s.socksProxyPass
|
||||
if len(user) > 255 {
|
||||
user = user[:255]
|
||||
}
|
||||
if len(pass) > 255 {
|
||||
pass = pass[:255]
|
||||
}
|
||||
authMsg := make([]byte, 0, 3+len(user)+len(pass))
|
||||
authMsg = append(authMsg, 1, byte(len(user)))
|
||||
authMsg = append(authMsg, []byte(user)...)
|
||||
authMsg = append(authMsg, byte(len(pass)))
|
||||
authMsg = append(authMsg, []byte(pass)...)
|
||||
if _, err := conn.Write(authMsg); err != nil {
|
||||
return fmt.Errorf("failed to write socks5 credentials: %w", err)
|
||||
}
|
||||
authResp := make([]byte, 2)
|
||||
if _, err := io.ReadFull(conn, authResp); err != nil {
|
||||
return fmt.Errorf("failed to read socks5 credentials resp: %w", err)
|
||||
}
|
||||
if authResp[1] != 0 {
|
||||
return ErrSocks5AuthFailed
|
||||
}
|
||||
default:
|
||||
return ErrSocks5AuthFailed
|
||||
}
|
||||
|
||||
|
||||
@@ -85,6 +85,8 @@ type Config struct {
|
||||
DNSServer string // resolver used for target dials, e.g. "8.8.8.8:53"
|
||||
SOCKSProxyAddr string // optional outbound SOCKS5 proxy host
|
||||
SOCKSProxyPort int // optional outbound SOCKS5 proxy port
|
||||
SOCKSProxyUser string // optional username for SOCKS5 proxy auth (RFC 1929)
|
||||
SOCKSProxyPass string // optional password for SOCKS5 proxy auth (RFC 1929)
|
||||
|
||||
// --- transport tuning ---
|
||||
// TransportOptions carries transport-specific tuning. Use the Options
|
||||
@@ -128,6 +130,8 @@ func (s *Server) Run(ctx context.Context) error {
|
||||
DNSServer: s.cfg.DNSServer,
|
||||
SOCKSProxyAddr: s.cfg.SOCKSProxyAddr,
|
||||
SOCKSProxyPort: s.cfg.SOCKSProxyPort,
|
||||
SOCKSProxyUser: s.cfg.SOCKSProxyUser,
|
||||
SOCKSProxyPass: s.cfg.SOCKSProxyPass,
|
||||
TransportOptions: s.cfg.TransportOptions,
|
||||
AuthHook: s.cfg.AuthHook,
|
||||
OnSessionOpen: s.cfg.OnSessionOpen,
|
||||
|
||||
Reference in New Issue
Block a user