1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-12-22 01:57:12 -05:00

allow redirection in dokodemo

This commit is contained in:
v2ray 2016-06-12 01:30:56 +02:00
parent 666dff02b0
commit 1c06fc216a
4 changed files with 57 additions and 5 deletions

View File

@ -5,6 +5,7 @@ import (
) )
type Config struct { type Config struct {
FollowRedirect bool
Address v2net.Address Address v2net.Address
Port v2net.Port Port v2net.Port
Network *v2net.NetworkList Network *v2net.NetworkList

View File

@ -16,6 +16,7 @@ func (this *Config) UnmarshalJSON(data []byte) error {
PortValue v2net.Port `json:"port"` PortValue v2net.Port `json:"port"`
NetworkList *v2net.NetworkList `json:"network"` NetworkList *v2net.NetworkList `json:"network"`
TimeoutValue int `json:"timeout"` TimeoutValue int `json:"timeout"`
Redirect bool `json:"followRedirect"`
} }
rawConfig := new(DokodemoConfig) rawConfig := new(DokodemoConfig)
if err := json.Unmarshal(data, rawConfig); err != nil { if err := json.Unmarshal(data, rawConfig); err != nil {
@ -25,6 +26,7 @@ func (this *Config) UnmarshalJSON(data []byte) error {
this.Port = rawConfig.PortValue this.Port = rawConfig.PortValue
this.Network = rawConfig.NetworkList this.Network = rawConfig.NetworkList
this.Timeout = rawConfig.TimeoutValue this.Timeout = rawConfig.TimeoutValue
this.FollowRedirect = rawConfig.Redirect
return nil return nil
} }

View File

@ -2,6 +2,7 @@ package dokodemo
import ( import (
"sync" "sync"
"syscall"
"github.com/v2ray/v2ray-core/app" "github.com/v2ray/v2ray-core/app"
"github.com/v2ray/v2ray-core/app/dispatcher" "github.com/v2ray/v2ray-core/app/dispatcher"
@ -14,6 +15,8 @@ import (
"github.com/v2ray/v2ray-core/transport/hub" "github.com/v2ray/v2ray-core/transport/hub"
) )
const SO_ORIGINAL_DST = 80
type DokodemoDoor struct { type DokodemoDoor struct {
tcpMutex sync.RWMutex tcpMutex sync.RWMutex
udpMutex sync.RWMutex udpMutex sync.RWMutex
@ -129,7 +132,16 @@ func (this *DokodemoDoor) ListenTCP() error {
func (this *DokodemoDoor) HandleTCPConnection(conn *hub.Connection) { func (this *DokodemoDoor) HandleTCPConnection(conn *hub.Connection) {
defer conn.Close() 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() defer ray.InboundOutput().Release()
var inputFinish, outputFinish sync.Mutex var inputFinish, outputFinish sync.Mutex
@ -160,6 +172,23 @@ func (this *DokodemoDoor) HandleTCPConnection(conn *hub.Connection) {
inputFinish.Lock() 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() { func init() {
internal.MustRegisterInboundHandlerCreator("dokodemo-door", internal.MustRegisterInboundHandlerCreator("dokodemo-door",
func(space app.Space, rawConfig interface{}, meta *proxy.InboundHandlerMeta) (proxy.InboundHandler, error) { func(space app.Space, rawConfig interface{}, meta *proxy.InboundHandlerMeta) (proxy.InboundHandler, error) {

View File

@ -1,12 +1,18 @@
package hub package hub
import ( import (
"errors"
"net" "net"
"reflect"
"time" "time"
"github.com/v2ray/v2ray-core/transport" "github.com/v2ray/v2ray-core/transport"
) )
var (
ErrInvalidConn = errors.New("Invalid Connection.")
)
type ConnectionHandler func(*Connection) type ConnectionHandler func(*Connection)
type ConnectionManager interface { type ConnectionManager interface {
@ -73,3 +79,17 @@ func (this *Connection) SetReusable(reusable bool) {
func (this *Connection) Reusable() bool { func (this *Connection) Reusable() bool {
return this.reusable return this.reusable
} }
func (this *Connection) SysFd() (int, error) {
cv := reflect.ValueOf(this.conn)
switch ce := cv.Elem(); ce.Kind() {
case reflect.Struct:
netfd := ce.FieldByName("conn").FieldByName("fd")
switch fe := netfd.Elem(); fe.Kind() {
case reflect.Struct:
fd := fe.FieldByName("sysfd")
return int(fd.Int()), nil
}
}
return 0, ErrInvalidConn
}