mirror of
https://github.com/SagerNet/sing-tun.git
synced 2025-04-04 04:17:39 +03:00
Add auto-redirect
This commit is contained in:
parent
ad763519ff
commit
67a5b408ef
9 changed files with 944 additions and 10 deletions
88
redirect_server.go
Normal file
88
redirect_server.go
Normal file
|
@ -0,0 +1,88 @@
|
|||
//go:build linux
|
||||
|
||||
package tun
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net"
|
||||
"net/netip"
|
||||
"time"
|
||||
|
||||
"github.com/sagernet/sing/common/atomic"
|
||||
"github.com/sagernet/sing/common/control"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
"github.com/sagernet/sing/common/logger"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
)
|
||||
|
||||
const ProtocolRedirect = "redirect"
|
||||
|
||||
type redirectServer struct {
|
||||
ctx context.Context
|
||||
handler Handler
|
||||
logger logger.Logger
|
||||
listenAddr netip.Addr
|
||||
listener *net.TCPListener
|
||||
inShutdown atomic.Bool
|
||||
}
|
||||
|
||||
func newRedirectServer(ctx context.Context, handler Handler, logger logger.Logger, listenAddr netip.Addr) *redirectServer {
|
||||
return &redirectServer{
|
||||
ctx: ctx,
|
||||
handler: handler,
|
||||
logger: logger,
|
||||
listenAddr: listenAddr,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *redirectServer) Start() error {
|
||||
var listenConfig net.ListenConfig
|
||||
// listenConfig.KeepAlive = C.TCPKeepAliveInitial
|
||||
listenConfig.KeepAlive = 10 * time.Minute
|
||||
listener, err := listenConfig.Listen(s.ctx, M.NetworkFromNetAddr("tcp", s.listenAddr), M.SocksaddrFrom(s.listenAddr, 0).String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.listener = listener.(*net.TCPListener)
|
||||
go s.loopIn()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *redirectServer) Close() error {
|
||||
s.inShutdown.Store(true)
|
||||
return s.listener.Close()
|
||||
}
|
||||
|
||||
func (s *redirectServer) loopIn() {
|
||||
for {
|
||||
conn, err := s.listener.AcceptTCP()
|
||||
if err != nil {
|
||||
var netError net.Error
|
||||
//goland:noinspection GoDeprecation
|
||||
//nolint:staticcheck
|
||||
if errors.As(err, &netError) && netError.Temporary() {
|
||||
s.logger.Error(err)
|
||||
continue
|
||||
}
|
||||
if s.inShutdown.Load() && E.IsClosed(err) {
|
||||
return
|
||||
}
|
||||
s.listener.Close()
|
||||
s.logger.Error("serve error: ", err)
|
||||
continue
|
||||
}
|
||||
var metadata M.Metadata
|
||||
metadata.Protocol = ProtocolRedirect
|
||||
metadata.Source = M.SocksaddrFromNet(conn.RemoteAddr())
|
||||
destination, err := control.GetOriginalDestination(conn)
|
||||
if err != nil {
|
||||
_ = conn.SetLinger(0)
|
||||
_ = conn.Close()
|
||||
s.logger.Error("process connection from ", metadata.Source, ": invalid connection: ", err)
|
||||
continue
|
||||
}
|
||||
metadata.Destination = M.SocksaddrFromNetIP(destination)
|
||||
go s.handler.NewConnection(s.ctx, conn, metadata)
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue