|
|
@@ -2,6 +2,7 @@ package dokodemo
|
|
|
|
|
|
import (
|
|
|
"sync"
|
|
|
+ "syscall"
|
|
|
|
|
|
"github.com/v2ray/v2ray-core/app"
|
|
|
"github.com/v2ray/v2ray-core/app/dispatcher"
|
|
|
@@ -14,6 +15,8 @@ import (
|
|
|
"github.com/v2ray/v2ray-core/transport/hub"
|
|
|
)
|
|
|
|
|
|
+const SO_ORIGINAL_DST = 80
|
|
|
+
|
|
|
type DokodemoDoor struct {
|
|
|
tcpMutex sync.RWMutex
|
|
|
udpMutex sync.RWMutex
|
|
|
@@ -129,7 +132,16 @@ func (this *DokodemoDoor) ListenTCP() error {
|
|
|
func (this *DokodemoDoor) HandleTCPConnection(conn *hub.Connection) {
|
|
|
defer conn.Close()
|
|
|
|
|
|
- ray := this.packetDispatcher.DispatchToOutbound(v2net.TCPDestination(this.address, this.port))
|
|
|
+ dest := v2net.TCPDestination(this.address, this.port)
|
|
|
+ if this.config.FollowRedirect {
|
|
|
+ originalDest := GetOriginalDestination(conn)
|
|
|
+ if originalDest != nil {
|
|
|
+ log.Info("Dokodemo: Following redirect to: ", originalDest)
|
|
|
+ dest = originalDest
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ ray := this.packetDispatcher.DispatchToOutbound(dest)
|
|
|
defer ray.InboundOutput().Release()
|
|
|
|
|
|
var inputFinish, outputFinish sync.Mutex
|
|
|
@@ -160,6 +172,23 @@ func (this *DokodemoDoor) HandleTCPConnection(conn *hub.Connection) {
|
|
|
inputFinish.Lock()
|
|
|
}
|
|
|
|
|
|
+func GetOriginalDestination(conn *hub.Connection) v2net.Destination {
|
|
|
+ fd, err := conn.SysFd()
|
|
|
+ if err != nil {
|
|
|
+ log.Info("Dokodemo: Failed to get original destination: ", err)
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+
|
|
|
+ addr, err := syscall.GetsockoptIPv6Mreq(fd, syscall.IPPROTO_IP, SO_ORIGINAL_DST)
|
|
|
+ if err != nil {
|
|
|
+ log.Info("Dokodemo: Failed to call getsockopt: ", err)
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ ip := v2net.IPAddress(addr.Multiaddr[4:8])
|
|
|
+ port := uint16(addr.Multiaddr[2])<<8 + uint16(addr.Multiaddr[3])
|
|
|
+ return v2net.TCPDestination(ip, v2net.Port(port))
|
|
|
+}
|
|
|
+
|
|
|
func init() {
|
|
|
internal.MustRegisterInboundHandlerCreator("dokodemo-door",
|
|
|
func(space app.Space, rawConfig interface{}, meta *proxy.InboundHandlerMeta) (proxy.InboundHandler, error) {
|