Compare commits

...

17 Commits
v0.12 ... v0.14

Author SHA1 Message Date
V2Ray
790f6c038c Fix field rule 2015-11-22 22:14:27 +01:00
V2Ray
1cdd3e6647 test case for ip rule 2015-11-22 21:16:28 +01:00
V2Ray
fb1dda5a19 Update config files 2015-11-22 21:05:16 +01:00
V2Ray
46b81b7e98 Update version for next release 2015-11-22 17:45:42 +01:00
V2Ray
12e72509a5 code ready for selective routing 2015-11-22 17:41:52 +01:00
V2Ray
f4ec19625e Implementation of rules router 2015-11-22 12:05:21 +01:00
V2Ray
d48ac4418f config for rule based router 2015-11-21 21:43:40 +01:00
V2Ray
794b5081e3 Simplify swap 2015-11-17 14:26:13 +01:00
V2Ray
1b8e100879 validation reader for vmess 2015-11-15 21:54:28 +01:00
V2Ray
57dc6c69f1 Router config 2015-11-14 14:24:56 +01:00
V2Ray
1d4b98ab9a Outbound detour config 2015-11-13 23:43:58 +01:00
V2Ray
8597642002 UDP support for dokodemo door 2015-11-11 00:08:43 +01:00
V2Ray
b6cebd127d fuzz test for socks udp 2015-11-10 18:16:13 +01:00
V2Ray
3a6844f482 reduce number of iterations of vmess fuzzing test. 2015-11-10 12:25:26 +01:00
V2Ray
bd48556b98 Smarter reader generator 2015-11-10 12:13:01 +01:00
V2Ray
2a6f4740c1 fuzzing test for vmess protocol 2015-11-10 00:05:25 +01:00
V2Ray
d34678d9a6 fuzzing test for socks protocol 2015-11-09 23:52:31 +01:00
34 changed files with 986 additions and 62 deletions

View File

@@ -1,11 +1,11 @@
package config
type RouterConfig interface {
Strategy() string
Settings() interface{}
}
import (
routerconfig "github.com/v2ray/v2ray-core/app/router/config"
v2net "github.com/v2ray/v2ray-core/common/net"
)
type ConnectionTag string
type DetourTag string
type ConnectionConfig interface {
Protocol() string
@@ -16,21 +16,24 @@ type LogConfig interface {
AccessLog() string
}
type PortRange interface {
From() uint16
To() uint16
}
type InboundDetourConfig interface {
Protocol() string
PortRange() PortRange
PortRange() v2net.PortRange
Settings() interface{}
}
type OutboundDetourConfig interface {
Protocol() string
Tag() DetourTag
Settings() interface{}
}
type PointConfig interface {
Port() uint16
LogConfig() LogConfig
RouterConfig() routerconfig.RouterConfig
InboundConfig() ConnectionConfig
OutboundConfig() ConnectionConfig
InboundDetours() []InboundDetourConfig
OutboundDetours() []OutboundDetourConfig
}

View File

@@ -3,21 +3,22 @@ package json
import (
"encoding/json"
"github.com/v2ray/v2ray-core/app/point/config"
v2net "github.com/v2ray/v2ray-core/common/net"
v2netjson "github.com/v2ray/v2ray-core/common/net/json"
proxyconfig "github.com/v2ray/v2ray-core/proxy/common/config"
)
type InboundDetourConfig struct {
ProtocolValue string `json:"protocol"`
PortRangeValue *PortRange `json:"port"`
SettingsValue json.RawMessage `json:"settings"`
ProtocolValue string `json:"protocol"`
PortRangeValue *v2netjson.PortRange `json:"port"`
SettingsValue json.RawMessage `json:"settings"`
}
func (this *InboundDetourConfig) Protocol() string {
return this.ProtocolValue
}
func (this *InboundDetourConfig) PortRange() config.PortRange {
func (this *InboundDetourConfig) PortRange() v2net.PortRange {
return this.PortRangeValue
}

View File

@@ -6,17 +6,21 @@ import (
"os"
"github.com/v2ray/v2ray-core/app/point/config"
routerconfig "github.com/v2ray/v2ray-core/app/router/config"
routerconfigjson "github.com/v2ray/v2ray-core/app/router/config/json"
"github.com/v2ray/v2ray-core/common/log"
proxyconfig "github.com/v2ray/v2ray-core/proxy/common/config"
)
// Config is the config for Point server.
type Config struct {
PortValue uint16 `json:"port"` // Port of this Point server.
LogConfigValue *LogConfig `json:"log"`
InboundConfigValue *ConnectionConfig `json:"inbound"`
OutboundConfigValue *ConnectionConfig `json:"outbound"`
InboundDetoursValue []*InboundDetourConfig `json:"inboundDetour"`
PortValue uint16 `json:"port"` // Port of this Point server.
LogConfigValue *LogConfig `json:"log"`
RouterConfigValue *routerconfigjson.RouterConfig `json:"router"`
InboundConfigValue *ConnectionConfig `json:"inbound"`
OutboundConfigValue *ConnectionConfig `json:"outbound"`
InboundDetoursValue []*InboundDetourConfig `json:"inboundDetour"`
OutboundDetoursValue []*OutboundDetourConfig `json:"outboundDetour"`
}
func (config *Config) Port() uint16 {
@@ -30,6 +34,13 @@ func (config *Config) LogConfig() config.LogConfig {
return config.LogConfigValue
}
func (this *Config) RouterConfig() routerconfig.RouterConfig {
if this.RouterConfigValue == nil {
return nil
}
return this.RouterConfigValue
}
func (config *Config) InboundConfig() config.ConnectionConfig {
if config.InboundConfigValue == nil {
return nil
@@ -52,6 +63,14 @@ func (this *Config) InboundDetours() []config.InboundDetourConfig {
return detours
}
func (this *Config) OutboundDetours() []config.OutboundDetourConfig {
detours := make([]config.OutboundDetourConfig, len(this.OutboundDetoursValue))
for idx, detour := range this.OutboundDetoursValue {
detours[idx] = detour
}
return detours
}
func LoadConfig(file string) (*Config, error) {
fixedFile := os.ExpandEnv(file)
rawConfig, err := ioutil.ReadFile(fixedFile)

View File

@@ -0,0 +1,26 @@
package json
import (
"encoding/json"
"github.com/v2ray/v2ray-core/app/point/config"
proxyconfig "github.com/v2ray/v2ray-core/proxy/common/config"
)
type OutboundDetourConfig struct {
ProtocolValue string `json:"protocol"`
TagValue string `json:"tag"`
SettingsValue json.RawMessage `json:"settings"`
}
func (this *OutboundDetourConfig) Protocol() string {
return this.ProtocolValue
}
func (this *OutboundDetourConfig) Tag() config.DetourTag {
return config.DetourTag(this.TagValue)
}
func (this *OutboundDetourConfig) Settings() interface{} {
return loadConnectionConfig(this.SettingsValue, this.ProtocolValue, proxyconfig.TypeOutbound)
}

View File

@@ -2,6 +2,8 @@ package mocks
import (
"github.com/v2ray/v2ray-core/app/point/config"
routerconfig "github.com/v2ray/v2ray-core/app/router/config"
v2net "github.com/v2ray/v2ray-core/common/net"
)
type ConnectionConfig struct {
@@ -39,20 +41,31 @@ type InboundDetourConfig struct {
PortRangeValue *PortRange
}
func (this *InboundDetourConfig) PortRange() config.PortRange {
func (this *InboundDetourConfig) PortRange() v2net.PortRange {
return this.PortRangeValue
}
type OutboundDetourConfig struct {
ConnectionConfig
TagValue config.DetourTag
}
func (this *OutboundDetourConfig) Tag() config.DetourTag {
return this.TagValue
}
func (config *LogConfig) AccessLog() string {
return config.AccessLogValue
}
type Config struct {
PortValue uint16
LogConfigValue *LogConfig
InboundConfigValue *ConnectionConfig
OutboundConfigValue *ConnectionConfig
InboundDetoursValue []*InboundDetourConfig
PortValue uint16
LogConfigValue *LogConfig
RouterConfigValue routerconfig.RouterConfig
InboundConfigValue *ConnectionConfig
OutboundConfigValue *ConnectionConfig
InboundDetoursValue []*InboundDetourConfig
OutboundDetoursValue []*OutboundDetourConfig
}
func (config *Config) Port() uint16 {
@@ -63,6 +76,10 @@ func (config *Config) LogConfig() config.LogConfig {
return config.LogConfigValue
}
func (this *Config) RouterConfig() routerconfig.RouterConfig {
return this.RouterConfigValue
}
func (config *Config) InboundConfig() config.ConnectionConfig {
return config.InboundConfigValue
}
@@ -78,3 +95,11 @@ func (this *Config) InboundDetours() []config.InboundDetourConfig {
}
return detours
}
func (this *Config) OutboundDetours() []config.OutboundDetourConfig {
detours := make([]config.OutboundDetourConfig, len(this.OutboundDetoursValue))
for idx, detour := range this.OutboundDetoursValue {
detours[idx] = detour
}
return detours
}

View File

@@ -2,6 +2,7 @@ package point
import (
"github.com/v2ray/v2ray-core/app/point/config"
"github.com/v2ray/v2ray-core/app/router"
"github.com/v2ray/v2ray-core/common/log"
v2net "github.com/v2ray/v2ray-core/common/net"
"github.com/v2ray/v2ray-core/common/retry"
@@ -11,10 +12,12 @@ import (
// Point is an single server in V2Ray system.
type Point struct {
port uint16
ich connhandler.InboundConnectionHandler
och connhandler.OutboundConnectionHandler
idh []*InboundDetourHandler
port uint16
ich connhandler.InboundConnectionHandler
och connhandler.OutboundConnectionHandler
idh []*InboundDetourHandler
odh map[config.DetourTag]connhandler.OutboundConnectionHandler
router router.Router
}
// NewPoint returns a new Point server based on given configuration.
@@ -65,6 +68,34 @@ func NewPoint(pConfig config.PointConfig) (*Point, error) {
}
}
outboundDetours := pConfig.OutboundDetours()
if len(outboundDetours) > 0 {
vpoint.odh = make(map[config.DetourTag]connhandler.OutboundConnectionHandler)
for _, detourConfig := range outboundDetours {
detourFactory := connhandler.GetOutboundConnectionHandlerFactory(detourConfig.Protocol())
if detourFactory == nil {
log.Error("Unknown detour outbound connection handler factory %s", detourConfig.Protocol())
return nil, config.BadConfiguration
}
detourHandler, err := detourFactory.Create(detourConfig.Settings())
if err != nil {
log.Error("Failed to create detour outbound connection handler: %v", err)
return nil, err
}
vpoint.odh[detourConfig.Tag()] = detourHandler
}
}
routerConfig := pConfig.RouterConfig()
if routerConfig != nil {
r, err := router.CreateRouter(routerConfig.Strategy(), routerConfig.Settings())
if err != nil {
log.Error("Failed to create router: %v", err)
return nil, config.BadConfiguration
}
vpoint.router = r
}
return vpoint, nil
}
@@ -100,6 +131,19 @@ func (vp *Point) Start() error {
func (p *Point) DispatchToOutbound(packet v2net.Packet) ray.InboundRay {
direct := ray.NewRay()
dest := packet.Destination()
if p.router != nil {
tag, err := p.router.TakeDetour(dest)
if err == nil {
handler, found := p.odh[tag]
if found {
go handler.Dispatch(packet, direct)
return direct
}
}
}
go p.och.Dispatch(packet, direct)
return direct
}

View File

@@ -0,0 +1,6 @@
package config
type RouterConfig interface {
Strategy() string
Settings() interface{}
}

View File

@@ -0,0 +1,25 @@
package json
type ConfigObjectCreator func() interface{}
var (
configCache map[string]ConfigObjectCreator
)
func RegisterRouterConfig(strategy string, creator ConfigObjectCreator) error {
// TODO: check strategy
configCache[strategy] = creator
return nil
}
func CreateRouterConfig(strategy string) interface{} {
creator, found := configCache[strategy]
if !found {
return nil
}
return creator()
}
func init() {
configCache = make(map[string]ConfigObjectCreator)
}

View File

@@ -0,0 +1,26 @@
package json
import (
"encoding/json"
"github.com/v2ray/v2ray-core/common/log"
)
type RouterConfig struct {
StrategyValue string `json:"strategy"`
SettingsValue json.RawMessage `json:"settings"`
}
func (this *RouterConfig) Strategy() string {
return this.StrategyValue
}
func (this *RouterConfig) Settings() interface{} {
settings := CreateRouterConfig(this.Strategy())
err := json.Unmarshal(this.SettingsValue, settings)
if err != nil {
log.Error("Failed to load router settings: %v", err)
return nil
}
return settings
}

View File

@@ -12,7 +12,7 @@ var (
)
type Router interface {
TakeDetour(v2net.Packet) (config.ConnectionTag, error)
TakeDetour(v2net.Destination) (config.DetourTag, error)
}
type RouterFactory interface {

View File

@@ -0,0 +1,93 @@
package json
import (
"encoding/json"
"errors"
"net"
"strings"
v2net "github.com/v2ray/v2ray-core/common/net"
v2netjson "github.com/v2ray/v2ray-core/common/net/json"
)
type FieldRule struct {
Rule
Domain string
IP *net.IPNet
Port v2net.PortRange
Network v2net.NetworkList
}
func (this *FieldRule) Apply(dest v2net.Destination) bool {
address := dest.Address()
if len(this.Domain) > 0 {
if !address.IsDomain() || !strings.Contains(address.Domain(), this.Domain) {
return false
}
}
if this.IP != nil {
if !(address.IsIPv4() || address.IsIPv6()) || !this.IP.Contains(address.IP()) {
return false
}
}
if this.Port != nil {
port := address.Port()
if port < this.Port.From() || port > this.Port.To() {
return false
}
}
if this.Network != nil {
if !this.Network.HasNetwork(v2net.Network(dest.Network())) {
return false
}
}
return true
}
func (this *FieldRule) UnmarshalJSON(data []byte) error {
type RawFieldRule struct {
Rule
Domain string `json:"domain"`
IP string `json:"ip"`
Port *v2netjson.PortRange `json:"port"`
Network *v2netjson.NetworkList `json:"network"`
}
rawFieldRule := RawFieldRule{}
err := json.Unmarshal(data, &rawFieldRule)
if err != nil {
return err
}
this.Type = rawFieldRule.Type
this.OutboundTag = rawFieldRule.OutboundTag
hasField := false
if len(rawFieldRule.Domain) > 0 {
this.Domain = rawFieldRule.Domain
hasField = true
}
if len(rawFieldRule.IP) > 0 {
_, ipNet, err := net.ParseCIDR(rawFieldRule.IP)
if err != nil {
return errors.New("Invalid IP range in router rule: " + err.Error())
}
this.IP = ipNet
hasField = true
}
if rawFieldRule.Port != nil {
this.Port = rawFieldRule.Port
hasField = true
}
if rawFieldRule.Network != nil {
this.Network = rawFieldRule.Network
hasField = true
}
if !hasField {
return errors.New("This rule has no effective fields.")
}
return nil
}

View File

@@ -0,0 +1,71 @@
package json
import (
"testing"
v2net "github.com/v2ray/v2ray-core/common/net"
v2nettesting "github.com/v2ray/v2ray-core/common/net/testing"
"github.com/v2ray/v2ray-core/testing/unit"
)
func TestDomainMatching(t *testing.T) {
assert := unit.Assert(t)
rule := &FieldRule{
Domain: "v2ray.com",
}
dest := v2net.NewTCPDestination(v2net.DomainAddress("www.v2ray.com", 80))
assert.Bool(rule.Apply(dest)).IsTrue()
}
func TestPortMatching(t *testing.T) {
assert := unit.Assert(t)
rule := &FieldRule{
Port: &v2nettesting.PortRange{
FromValue: 0,
ToValue: 100,
},
}
dest := v2net.NewTCPDestination(v2net.DomainAddress("www.v2ray.com", 80))
assert.Bool(rule.Apply(dest)).IsTrue()
}
func TestIPMatching(t *testing.T) {
assert := unit.Assert(t)
rawJson := `{
"type": "field",
"ip": "10.0.0.0/8",
"tag": "test"
}`
rule := parseRule([]byte(rawJson))
dest := v2net.NewTCPDestination(v2net.IPAddress([]byte{10, 0, 0, 1}, 80))
assert.Bool(rule.Apply(dest)).IsTrue()
}
func TestPortNotMatching(t *testing.T) {
assert := unit.Assert(t)
rawJson := `{
"type": "field",
"port": "80-100",
"tag": "test"
}`
rule := parseRule([]byte(rawJson))
dest := v2net.NewTCPDestination(v2net.IPAddress([]byte{10, 0, 0, 1}, 79))
assert.Bool(rule.Apply(dest)).IsFalse()
}
func TestDomainNotMatching(t *testing.T) {
assert := unit.Assert(t)
rawJson := `{
"type": "field",
"domain": "google.com",
"tag": "test"
}`
rule := parseRule([]byte(rawJson))
dest := v2net.NewTCPDestination(v2net.IPAddress([]byte{10, 0, 0, 1}, 79))
assert.Bool(rule.Apply(dest)).IsFalse()
}

View File

@@ -0,0 +1,47 @@
package json
import (
"encoding/json"
v2routerconfigjson "github.com/v2ray/v2ray-core/app/router/config/json"
"github.com/v2ray/v2ray-core/app/router/rules/config"
"github.com/v2ray/v2ray-core/common/log"
)
type RouterRuleConfig struct {
RuleList []json.RawMessage `json:"rules"`
}
func parseRule(msg json.RawMessage) config.Rule {
rule := new(Rule)
err := json.Unmarshal(msg, rule)
if err != nil {
log.Error("Invalid router rule: %v", err)
return nil
}
if rule.Type == "field" {
fieldrule := new(FieldRule)
err = json.Unmarshal(msg, fieldrule)
if err != nil {
log.Error("Invalid field rule: %v", err)
return nil
}
return fieldrule
}
log.Error("Unknown router rule type: %s", rule.Type)
return nil
}
func (this *RouterRuleConfig) Rules() []config.Rule {
rules := make([]config.Rule, len(this.RuleList))
for idx, rawRule := range this.RuleList {
rules[idx] = parseRule(rawRule)
}
return rules
}
func init() {
v2routerconfigjson.RegisterRouterConfig("rules", func() interface{} {
return new(RouterRuleConfig)
})
}

View File

@@ -0,0 +1,19 @@
package json
import (
"github.com/v2ray/v2ray-core/app/point/config"
v2net "github.com/v2ray/v2ray-core/common/net"
)
type Rule struct {
Type string `json:"type"`
OutboundTag string `json:"outboundTag"`
}
func (this *Rule) Tag() config.DetourTag {
return config.DetourTag(this.OutboundTag)
}
func (this *Rule) Apply(dest v2net.Destination) bool {
return false
}

View File

@@ -0,0 +1,5 @@
package config
type RouterRuleConfig interface {
Rules() []Rule
}

View File

@@ -0,0 +1,11 @@
package config
import (
"github.com/v2ray/v2ray-core/app/point/config"
v2net "github.com/v2ray/v2ray-core/common/net"
)
type Rule interface {
Tag() config.DetourTag
Apply(dest v2net.Destination) bool
}

View File

@@ -0,0 +1,51 @@
package rules
import (
"errors"
pointconfig "github.com/v2ray/v2ray-core/app/point/config"
"github.com/v2ray/v2ray-core/app/router"
"github.com/v2ray/v2ray-core/app/router/rules/config"
"github.com/v2ray/v2ray-core/app/router/rules/config/json"
v2net "github.com/v2ray/v2ray-core/common/net"
)
var (
InvalidRule = errors.New("Invalid Rule")
NoRuleApplicable = errors.New("No rule applicable")
EmptyTag = pointconfig.DetourTag("")
)
type Router struct {
rules []config.Rule
}
func (this *Router) TakeDetour(dest v2net.Destination) (pointconfig.DetourTag, error) {
for _, rule := range this.rules {
if rule.Apply(dest) {
return rule.Tag(), nil
}
}
return EmptyTag, NoRuleApplicable
}
type RouterFactory struct {
}
func (this *RouterFactory) Create(rawConfig interface{}) (router.Router, error) {
config := rawConfig.(*json.RouterRuleConfig)
rules := config.Rules()
for _, rule := range rules {
if rule == nil {
return nil, InvalidRule
}
}
return &Router{
rules: rules,
}, nil
}
func init() {
router.RegisterRouter("rules", &RouterFactory{})
}

View File

@@ -1,25 +0,0 @@
package wildcard_router
import (
"github.com/v2ray/v2ray-core/app/point/config"
"github.com/v2ray/v2ray-core/app/router"
v2net "github.com/v2ray/v2ray-core/common/net"
)
type WildcardRouter struct {
}
func (router *WildcardRouter) TakeDetour(packet v2net.Packet) (config.ConnectionTag, error) {
return "", nil
}
type WildcardRouterFactory struct {
}
func (factory *WildcardRouterFactory) Create(rawConfig interface{}) (router.Router, error) {
return &WildcardRouter{}, nil
}
func init() {
router.RegisterRouter("wildcard", &WildcardRouterFactory{})
}

View File

@@ -22,9 +22,7 @@ func (queue timedQueueImpl) Less(i, j int) bool {
}
func (queue timedQueueImpl) Swap(i, j int) {
tmp := queue[i]
queue[i] = queue[j]
queue[j] = tmp
queue[i], queue[j] = queue[j], queue[i]
}
func (queue *timedQueueImpl) Push(value interface{}) {

6
common/net/portrange.go Normal file
View File

@@ -0,0 +1,6 @@
package net
type PortRange interface {
From() uint16
To() uint16
}

View File

@@ -0,0 +1,14 @@
package testing
type PortRange struct {
FromValue uint16
ToValue uint16
}
func (this *PortRange) From() uint16 {
return this.FromValue
}
func (this *PortRange) To() uint16 {
return this.ToValue
}

View File

@@ -8,7 +8,7 @@ import (
)
var (
version = "0.11"
version = "0.14"
build = "Custom"
codename = "Post Apocalypse"
intro = "A stable and unbreakable connection for everyone."

View File

@@ -35,15 +35,59 @@ func NewDokodemoDoor(dispatcher app.PacketDispatcher, config *json.DokodemoConfi
}
func (this *DokodemoDoor) Listen(port uint16) error {
this.accepting = true
if this.config.Network.HasNetwork(v2net.TCPNetwork) {
err := this.ListenTCP(port)
if err != nil {
return err
}
}
if this.config.Network.HasNetwork(v2net.UDPNetwork) {
err := this.ListenUDP(port)
if err != nil {
return err
}
}
return nil
}
func (this *DokodemoDoor) ListenUDP(port uint16) error {
udpConn, err := net.ListenUDP("udp", &net.UDPAddr{
IP: []byte{0, 0, 0, 0},
Port: int(port),
Zone: "",
})
if err != nil {
log.Error("Dokodemo failed to listen on port %d: %v", port, err)
return err
}
go this.handleUDPPackets(udpConn)
return nil
}
func (this *DokodemoDoor) handleUDPPackets(udpConn *net.UDPConn) {
defer udpConn.Close()
for this.accepting {
buffer := alloc.NewBuffer()
nBytes, addr, err := udpConn.ReadFromUDP(buffer.Value)
buffer.Slice(0, nBytes)
if err != nil {
buffer.Release()
log.Error("Dokodemo failed to read from UDP: %v", err)
return
}
packet := v2net.NewPacket(v2net.NewUDPDestination(this.address), buffer, false)
ray := this.dispatcher.DispatchToOutbound(packet)
close(ray.InboundInput())
for payload := range ray.InboundOutput() {
udpConn.WriteToUDP(payload.Value, addr)
}
}
}
func (this *DokodemoDoor) ListenTCP(port uint16) error {
tcpListener, err := net.ListenTCP("tcp", &net.TCPAddr{
IP: []byte{0, 0, 0, 0},
@@ -54,7 +98,6 @@ func (this *DokodemoDoor) ListenTCP(port uint16) error {
log.Error("Dokodemo failed to listen on port %d: %v", port, err)
return err
}
this.accepting = true
go this.AcceptTCPConnections(tcpListener)
return nil
}

View File

@@ -11,6 +11,7 @@ import (
"github.com/v2ray/v2ray-core/proxy/dokodemo/config/json"
_ "github.com/v2ray/v2ray-core/proxy/freedom"
"github.com/v2ray/v2ray-core/testing/servers/tcp"
"github.com/v2ray/v2ray-core/testing/servers/udp"
"github.com/v2ray/v2ray-core/testing/unit"
)
@@ -75,3 +76,64 @@ func TestDokodemoTCP(t *testing.T) {
assert.String("Processed: " + data2Send).Equals(string(response[:nBytes]))
}
func TestDokodemoUDP(t *testing.T) {
assert := unit.Assert(t)
port := v2nettesting.PickPort()
data2Send := "Data to be sent to remote."
udpServer := &udp.Server{
Port: port,
MsgProcessor: func(data []byte) []byte {
buffer := make([]byte, 0, 2048)
buffer = append(buffer, []byte("Processed: ")...)
buffer = append(buffer, data...)
return buffer
},
}
_, err := udpServer.Start()
assert.Error(err).IsNil()
pointPort := v2nettesting.PickPort()
networkList := v2netjson.NetworkList([]string{"udp"})
config := mocks.Config{
PortValue: pointPort,
InboundConfigValue: &mocks.ConnectionConfig{
ProtocolValue: "dokodemo-door",
SettingsValue: &json.DokodemoConfig{
Host: "127.0.0.1",
Port: int(port),
Network: &networkList,
Timeout: 0,
},
},
OutboundConfigValue: &mocks.ConnectionConfig{
ProtocolValue: "freedom",
SettingsValue: nil,
},
}
point, err := point.NewPoint(&config)
assert.Error(err).IsNil()
err = point.Start()
assert.Error(err).IsNil()
udpClient, err := net.DialUDP("udp", nil, &net.UDPAddr{
IP: []byte{127, 0, 0, 1},
Port: int(pointPort),
Zone: "",
})
assert.Error(err).IsNil()
udpClient.Write([]byte(data2Send))
response := make([]byte, 1024)
nBytes, err := udpClient.Read(response)
assert.Error(err).IsNil()
udpClient.Close()
assert.String("Processed: " + data2Send).Equals(string(response[:nBytes]))
}

View File

@@ -0,0 +1,35 @@
package protocol
import (
"testing"
"github.com/v2ray/v2ray-core/testing/fuzzing"
)
const (
Iterations = int(500000)
)
func TestReadAuthentication(t *testing.T) {
for i := 0; i < Iterations; i++ {
ReadAuthentication(fuzzing.RandomReader())
}
}
func TestReadUserPassRequest(t *testing.T) {
for i := 0; i < Iterations; i++ {
ReadUserPassRequest(fuzzing.RandomReader())
}
}
func TestReadRequest(t *testing.T) {
for i := 0; i < Iterations; i++ {
ReadRequest(fuzzing.RandomReader())
}
}
func TestReadUDPRequest(t *testing.T) {
for i := 0; i < Iterations; i++ {
ReadUDPRequest(fuzzing.RandomBytes())
}
}

View File

@@ -0,0 +1,75 @@
package io
import (
"errors"
"hash/fnv"
"io"
"github.com/v2ray/v2ray-core/common/alloc"
"github.com/v2ray/v2ray-core/transport"
)
var (
TruncatedPayload = errors.New("Truncated payload.")
)
type ValidationReader struct {
reader io.Reader
buffer *alloc.Buffer
}
func NewValidationReader(reader io.Reader) *ValidationReader {
return &ValidationReader{
reader: reader,
buffer: alloc.NewLargeBuffer().Clear(),
}
}
func (this *ValidationReader) Read(data []byte) (int, error) {
nBytes, err := this.reader.Read(data)
if err != nil {
return nBytes, err
}
nBytesActual := 0
dataActual := data[:]
for {
payload, rest, err := parsePayload(data)
if err != nil {
return nBytesActual, err
}
copy(dataActual, payload)
nBytesActual += len(payload)
dataActual = dataActual[nBytesActual:]
if len(rest) == 0 {
break
}
data = rest
}
return nBytesActual, nil
}
func parsePayload(data []byte) (payload []byte, rest []byte, err error) {
dataLen := len(data)
if dataLen < 6 {
err = TruncatedPayload
return
}
payloadLen := int(data[0])<<8 + int(data[1])
if dataLen < payloadLen+6 {
err = TruncatedPayload
return
}
payload = data[6 : 6+payloadLen]
rest = data[6+payloadLen:]
fnv1a := fnv.New32a()
fnv1a.Write(payload)
actualHash := fnv1a.Sum32()
expectedHash := uint32(data[2])<<24 + uint32(data[3])<<16 + uint32(data[4])<<8 + uint32(data[5])
if actualHash != expectedHash {
err = transport.CorruptedPacket
return
}
return
}

View File

@@ -0,0 +1,29 @@
package mocks
import (
"github.com/v2ray/v2ray-core/proxy/vmess/config"
)
type StaticUser struct {
id *config.ID
}
func (this *StaticUser) ID() *config.ID {
return this.id
}
func (this *StaticUser) Level() config.UserLevel {
return config.UserLevelUntrusted
}
type StaticUserSet struct {
}
func (us *StaticUserSet) AddUser(user config.User) error {
return nil
}
func (us *StaticUserSet) GetUser(userhash []byte) (config.User, int64, bool) {
id, _ := config.NewID("703e9102-eb57-499c-8b59-faf4f371bb21")
return &StaticUser{id: id}, 0, true
}

View File

@@ -0,0 +1,15 @@
package protocol
import (
"testing"
"github.com/v2ray/v2ray-core/proxy/vmess/protocol/user/testing/mocks"
"github.com/v2ray/v2ray-core/testing/fuzzing"
)
func TestVMessRequestReader(t *testing.T) {
reader := NewVMessRequestReader(&mocks.StaticUserSet{})
for i := 0; i < 1000000; i++ {
reader.Read(fuzzing.RandomReader())
}
}

View File

@@ -25,5 +25,94 @@
}
]
}
},
"outboundDetour": [
{
"protocol": "freedom",
"settings": {},
"tag": "direct"
}
],
"router": {
"strategy": "rules",
"settings": {
"rules": [
{
"type": "field",
"ip": "0.0.0.0/8",
"outboundTag": "direct"
},
{
"type": "field",
"ip": "10.0.0.0/8",
"outboundTag": "direct"
},
{
"type": "field",
"ip": "100.64.0.0/10",
"outboundTag": "direct"
},
{
"type": "field",
"ip": "127.0.0.0/8",
"outboundTag": "direct"
},
{
"type": "field",
"ip": "169.254.0.0/16",
"outboundTag": "direct"
},
{
"type": "field",
"ip": "172.16.0.0/12",
"outboundTag": "direct"
},
{
"type": "field",
"ip": "192.0.0.0/24",
"outboundTag": "direct"
},
{
"type": "field",
"ip": "192.0.2.0/24",
"outboundTag": "direct"
},
{
"type": "field",
"ip": "192.168.0.0/16",
"outboundTag": "direct"
},
{
"type": "field",
"ip": "198.18.0.0/15",
"outboundTag": "direct"
},
{
"type": "field",
"ip": "198.51.100.0/24",
"outboundTag": "direct"
},
{
"type": "field",
"ip": "203.0.113.0/24",
"outboundTag": "direct"
},
{
"type": "field",
"ip": "::1/128",
"outboundTag": "direct"
},
{
"type": "field",
"ip": "fc00::/7",
"outboundTag": "direct"
},
{
"type": "field",
"ip": "fe80::/10",
"outboundTag": "direct"
}
]
}
}
}

View File

@@ -21,5 +21,94 @@
"outbound": {
"protocol": "freedom",
"settings": {}
},
"outboundDetour": [
{
"protocol": "blackhole",
"settings": {},
"tag": "blocked"
}
],
"router": {
"strategy": "rules",
"settings": {
"rules": [
{
"type": "field",
"ip": "0.0.0.0/8",
"outboundTag": "blocked"
},
{
"type": "field",
"ip": "10.0.0.0/8",
"outboundTag": "blocked"
},
{
"type": "field",
"ip": "100.64.0.0/10",
"outboundTag": "blocked"
},
{
"type": "field",
"ip": "127.0.0.0/8",
"outboundTag": "blocked"
},
{
"type": "field",
"ip": "169.254.0.0/16",
"outboundTag": "blocked"
},
{
"type": "field",
"ip": "172.16.0.0/12",
"outboundTag": "blocked"
},
{
"type": "field",
"ip": "192.0.0.0/24",
"outboundTag": "blocked"
},
{
"type": "field",
"ip": "192.0.2.0/24",
"outboundTag": "blocked"
},
{
"type": "field",
"ip": "192.168.0.0/16",
"outboundTag": "blocked"
},
{
"type": "field",
"ip": "198.18.0.0/15",
"outboundTag": "blocked"
},
{
"type": "field",
"ip": "198.51.100.0/24",
"outboundTag": "blocked"
},
{
"type": "field",
"ip": "203.0.113.0/24",
"outboundTag": "blocked"
},
{
"type": "field",
"ip": "::1/128",
"outboundTag": "blocked"
},
{
"type": "field",
"ip": "fc00::/7",
"outboundTag": "blocked"
},
{
"type": "field",
"ip": "fe80::/10",
"outboundTag": "blocked"
}
]
}
}
}

View File

@@ -9,9 +9,14 @@ import (
"github.com/v2ray/v2ray-core"
"github.com/v2ray/v2ray-core/app/point"
jsonconf "github.com/v2ray/v2ray-core/app/point/config/json"
_ "github.com/v2ray/v2ray-core/app/router/config/json"
_ "github.com/v2ray/v2ray-core/app/router/rules"
_ "github.com/v2ray/v2ray-core/app/router/rules/config/json"
"github.com/v2ray/v2ray-core/common/log"
// The following are neccesary as they register handlers in their init functions.
_ "github.com/v2ray/v2ray-core/proxy/blackhole"
_ "github.com/v2ray/v2ray-core/proxy/blackhole/config/json"
_ "github.com/v2ray/v2ray-core/proxy/dokodemo"
_ "github.com/v2ray/v2ray-core/proxy/dokodemo/config/json"
_ "github.com/v2ray/v2ray-core/proxy/freedom"

View File

@@ -0,0 +1,17 @@
package fuzzing
import (
"bytes"
"crypto/rand"
"io"
)
func RandomBytes() []byte {
buffer := make([]byte, 256)
rand.Read(buffer)
return buffer[1 : 1+int(buffer[0])]
}
func RandomReader() io.Reader {
return bytes.NewReader(RandomBytes())
}