mirror of
https://github.com/costinm/ugate.git
synced 2025-12-24 13:27:52 +08:00
Updates
This commit is contained in:
4
Makefile
4
Makefile
@@ -54,6 +54,10 @@ push/docker.ugate: docker push/ugate
|
||||
push/ugate:
|
||||
docker push ${IMAGE}:latest
|
||||
|
||||
build/android:
|
||||
cd android && gomobile bind -a -ldflags '-s -w' -target android -o android/ugate.aar .
|
||||
|
||||
|
||||
# Using Intellij plugin: missing manifest features
|
||||
# Build with buildpack: 30 sec to deploy
|
||||
# Build with docker: 26 sec
|
||||
|
||||
186
android/ugate.go
186
android/ugate.go
@@ -1,186 +0,0 @@
|
||||
package android
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/costinm/ugate"
|
||||
"github.com/costinm/ugate/pkg/local"
|
||||
"github.com/costinm/ugate/pkg/msgs"
|
||||
"github.com/costinm/ugate/pkg/udp"
|
||||
"github.com/costinm/ugate/pkg/ugatesvc"
|
||||
"github.com/costinm/ugate/pkg/auth"
|
||||
)
|
||||
/*
|
||||
gomobile bindings
|
||||
|
||||
- called 2x, once with lang=java and once with lang=go
|
||||
|
||||
- Signed integer and floating point types.
|
||||
|
||||
- String and boolean types.
|
||||
|
||||
- Byte slice types. Note that byte slices are passed by reference,
|
||||
and support mutation.
|
||||
|
||||
- Any function type all of whose parameters and results have
|
||||
supported types. Functions must return either no results,
|
||||
one result, or two results where the type of the second is
|
||||
the built-in 'error' type.
|
||||
|
||||
- Any interface type, all of whose exported methods have
|
||||
supported function types.
|
||||
|
||||
- Any struct type, all of whose exported methods have
|
||||
supported function types and all of whose exported fields
|
||||
have supported types.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
// Adapter from func to interface
|
||||
type HandlerCallbackFunc func(cmdS string, data []byte)
|
||||
|
||||
type MessageHandler interface {
|
||||
Handle(topic string, data []byte)
|
||||
}
|
||||
|
||||
var (
|
||||
ld *local.LLDiscovery
|
||||
gw *ugatesvc.UGate
|
||||
udpGate = udp.NewUDPGate(nil, nil)
|
||||
)
|
||||
|
||||
// Called to inject a message into Go impl
|
||||
func Send(cmdS string, data []byte) {
|
||||
switch cmdS {
|
||||
case "r":
|
||||
// refresh networks
|
||||
log.Println("UDS: refresh network (r)")
|
||||
go func() {
|
||||
time.Sleep(2 * time.Second)
|
||||
ld.RefreshNetworks()
|
||||
}()
|
||||
|
||||
// TODO: P - properties, json
|
||||
// CON - STOP/START - set connected WIFI
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
// Android and device version of DMesh.
|
||||
func InitDmesh(callbackFunc MessageHandler) {
|
||||
log.Print("Starting native process pwd=", os.Getenv("PWD"), os.Environ())
|
||||
|
||||
// SYSTEMSERVERCLASSPATH=/system/framework/services.jar:/system/framework/ethernet-service.jar:/system/framework/wifi-service.jar:/system/framework/com.android.location.provider.jar
|
||||
// PATH=/sbin:/system/sbin:/system/bin:/system/xbin:/odm/bin:/vendor/bin:/vendor/xbin
|
||||
// STORAGE=/storage/emulated/0/Android/data/com.github.costinm.dmwifi/files
|
||||
// ANDROID_DATA=/data
|
||||
// ANDROID_SOCKET_zygote_secondary=12
|
||||
// ASEC_MOUNTPOINT=/mnt/asec
|
||||
// EXTERNAL_STORAGE=/sdcard
|
||||
// ANDROID_BOOTLOGO=1
|
||||
// ANDROID_ASSETS=/system/app
|
||||
// BASE=/data/user/0/com.github.costinm.dmwifi/files
|
||||
// ANDROID_STORAGE=/storage
|
||||
// ANDROID_ROOT=/system
|
||||
// DOWNLOAD_CACHE=/data/cache
|
||||
// BOOTCLASSPATH=/system/framework/core-oj.jar:/system/framework/core-libart.jar:/system/framework/conscrypt.jar:/system/framework/okhttp.jar:/system/framework/bouncycastle.jar:/system/framework/apache-xml.jar:/system/framework/ext.jar:/system/framework/framework.jar:/system/framework/telephony-common.jar:/system/framework/voip-common.jar:/system/framework/ims-common.jar:/system/framework/android.hidl.base-V1.0-java.jar:/system/framework/android.hidl.manager-V1.0-java.jar:/system/framework/framework-oahl-backward-compatibility.jar:/system/framework/android.test.base.jar:/system/framework/com.google.vr.platform.jar]
|
||||
|
||||
cfgf := os.Getenv("BASE")
|
||||
if cfgf == "" {
|
||||
cfgf = os.Getenv("HOME")
|
||||
if cfgf == "" {
|
||||
cfgf = os.Getenv("TEMPDIR")
|
||||
}
|
||||
if cfgf == "" {
|
||||
cfgf = os.Getenv("TMP")
|
||||
}
|
||||
if cfgf == "" {
|
||||
cfgf = "/tmp"
|
||||
}
|
||||
}
|
||||
|
||||
cfgf += "/"
|
||||
|
||||
// File-based config
|
||||
config := ugatesvc.NewConf(cfgf)
|
||||
|
||||
//meshH := "v.webinf.info:5222" // ugatesvc.Conf(config, "MESH", "v.webinf.info:5222")
|
||||
|
||||
// Init or load certificates/keys
|
||||
authz := auth.NewAuth(config, os.Getenv("HOSTNAME"), "v.webinf.info")
|
||||
msgs.DefaultMux.Auth = authz
|
||||
|
||||
gcfg := &ugate.GateCfg{
|
||||
BasePort: 15000,
|
||||
}
|
||||
|
||||
GW := ugatesvc.NewGate(nil, authz, gcfg, nil)
|
||||
|
||||
// HTTPGate - common structures
|
||||
//GW := mesh.New(authz, nil)
|
||||
|
||||
// SSH transport + reverse streams.
|
||||
//sshg := sshgate.NewSSHGate(GW, authz)
|
||||
//GW.SSHGate = sshg
|
||||
//sshg.InitServer()
|
||||
//sshg.ListenSSH(":5222")
|
||||
//
|
||||
//// Connect to a mesh node
|
||||
//if meshH != "" {
|
||||
// GW.Vpn = meshH
|
||||
// go sshgate.MaintainVPNConnection(GW)
|
||||
//}
|
||||
|
||||
// Local discovery interface - multicast, local network IPs
|
||||
ld := local.NewLocal(GW, authz)
|
||||
go ld.PeriodicThread()
|
||||
local.ListenUDP(ld)
|
||||
|
||||
GW.Mux.HandleFunc("/dmesh/ll/if", ld.HttpGetLLIf)
|
||||
|
||||
|
||||
//h2s, err := h2.NewTransport(authz)
|
||||
//if err != nil {
|
||||
// log.Fatal(err)
|
||||
//}
|
||||
|
||||
// DNS capture, interpret the names, etc
|
||||
// Off until DNS moved to smaller package.
|
||||
//dnss, _ := dns.NewDmDns(5223)
|
||||
//GW.DNS = dnss
|
||||
//net.DefaultResolver.PreferGo = true
|
||||
//net.DefaultResolver.Dial = dns.DNSDialer(5223)
|
||||
|
||||
//udpNat := udp.NewUDPGate(GW)
|
||||
//udpNat.DNS = dnss
|
||||
|
||||
//hgw := httpproxy.NewHTTPGate(GW, h2s)
|
||||
//hgw.HttpProxyCapture("localhost:5204")
|
||||
|
||||
// Start a basic UI on the debug port
|
||||
// u, _ := ui.NewUI(GW, h2s, hgw, ld)
|
||||
|
||||
//udpNat.InitMux(h2s.LocalMux)
|
||||
|
||||
//// Periodic registrations.
|
||||
//m.Registry.RefreshNetworksPeriodic()
|
||||
|
||||
log.Printf("Loading with VIP6: %v ID64: %s\n",
|
||||
authz.VIP6,
|
||||
base64.RawURLEncoding.EncodeToString(authz.VIP6[8:]))
|
||||
|
||||
//dnss.Serve()
|
||||
//err = http.ListenAndServe("localhost:5227", u)
|
||||
//if err != nil {
|
||||
// log.Println(err)
|
||||
//}
|
||||
|
||||
// TODO: mux adapter, so we can exchange messages.
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -3,13 +3,15 @@ module github.com/costinm/ugate/cmd/ugate
|
||||
go 1.16
|
||||
|
||||
replace github.com/costinm/ugate => ../../
|
||||
|
||||
replace github.com/costinm/ugate/webrtc => ../../webrtc
|
||||
|
||||
replace github.com/costinm/ugate/dns => ../../dns
|
||||
|
||||
replace github.com/costinm/ugate/webpush => ../../webpush
|
||||
|
||||
require (
|
||||
github.com/costinm/ugate v0.0.0-20210221155556-10edd21fadbf
|
||||
|
||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68
|
||||
github.com/costinm/ugate v0.0.0-20210328173325-afc113d007e8
|
||||
github.com/costinm/ugate/dns v0.0.0-00010101000000-000000000000
|
||||
github.com/costinm/ugate/webpush v0.0.0-20210329161419-fd5474ea74fe
|
||||
)
|
||||
|
||||
26
cmd/ugate/go.sum
Normal file
26
cmd/ugate/go.sum
Normal file
@@ -0,0 +1,26 @@
|
||||
github.com/miekg/dns v1.1.40 h1:pyyPFfGMnciYUk/mXpKkVmeMQjfXqt3FAJ2hy7tPiLA=
|
||||
github.com/miekg/dns v1.1.40/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
12
cmd/ugate/testdata/ugate.json
vendored
12
cmd/ugate/testdata/ugate.json
vendored
@@ -33,14 +33,10 @@
|
||||
"hosts": {
|
||||
"localiperf": {
|
||||
"addr": "localhost:15102"
|
||||
},
|
||||
"h.webinf.info": {
|
||||
"addr": "h.webinf.info:15007",
|
||||
"id": "B5B6KYYUBVKCX4PWPWSWAIHW2X2D3Q4HZPJYWZ6UECL2PAODHTFA"
|
||||
},
|
||||
"c1.webinf.info": {
|
||||
"addr": "c1.webinf.info:15007"
|
||||
}
|
||||
},
|
||||
"remoteAccept": null
|
||||
"remoteAccept": {
|
||||
"h.webinf.info": "B5B6KYYUBVKCX4PWPWSWAIHW2X2D3Q4HZPJYWZ6UECL2PAODHTFA",
|
||||
"c1.webinf.info": ""
|
||||
}
|
||||
}
|
||||
16
cmd/ugate/testdata/ugate.yaml
vendored
16
cmd/ugate/testdata/ugate.yaml
vendored
@@ -44,19 +44,19 @@ hosts:
|
||||
addr: localhost:15102
|
||||
|
||||
# Live test server
|
||||
h.webinf.info:
|
||||
addr: h.webinf.info:15007
|
||||
id: B5B6KYYUBVKCX4PWPWSWAIHW2X2D3Q4HZPJYWZ6UECL2PAODHTFA
|
||||
|
||||
c1.webinf.info:
|
||||
addr: c1.webinf.info:15007
|
||||
# h.webinf.info:
|
||||
# addr: h.webinf.info:15007
|
||||
# id: B5B6KYYUBVKCX4PWPWSWAIHW2X2D3Q4HZPJYWZ6UECL2PAODHTFA
|
||||
#
|
||||
# c1.webinf.info:
|
||||
# addr: c1.webinf.info:15007
|
||||
|
||||
# Remote accept request (reverse forward, "-R")
|
||||
# Will also include relays, stun, etc.
|
||||
# TODO: could also be part of the hosts: definition, include a list
|
||||
# of ports. This way we don't dup the public key.
|
||||
remoteAccept:
|
||||
#h.webinf.info: "B5B6KYYUBVKCX4PWPWSWAIHW2X2D3Q4HZPJYWZ6UECL2PAODHTFA"
|
||||
h.webinf.info: "B5B6KYYUBVKCX4PWPWSWAIHW2X2D3Q4HZPJYWZ6UECL2PAODHTFA"
|
||||
|
||||
#c1.webinf.info: ""
|
||||
c1.webinf.info: ""
|
||||
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
_ "net/http/pprof"
|
||||
|
||||
"github.com/costinm/ugate/pkg/local"
|
||||
msgs "github.com/costinm/ugate/webpush"
|
||||
ug "github.com/costinm/ugate/pkg/ugatesvc"
|
||||
"github.com/costinm/ugate"
|
||||
"github.com/costinm/ugate/dns"
|
||||
"github.com/costinm/ugate/pkg/udp"
|
||||
"github.com/costinm/ugate/pkg/ugatesvc"
|
||||
)
|
||||
type startFunc func(ug *ugatesvc.UGate)
|
||||
var initHooks []func(gate *ugatesvc.UGate) startFunc
|
||||
|
||||
// Minimal TCP over H2 Gateway, defaulting to Istio ports and capture behavior.
|
||||
// There is no envoy - all traffic is upgraded to optional mTLS + H2 and sent to
|
||||
@@ -21,34 +25,54 @@ import (
|
||||
// - option to use mTLS - if the network is secure ( ipsec or equivalent ) no encryption
|
||||
// - detect TLS and pass it through
|
||||
// - inbound: extract metadata
|
||||
// - DNS and DNS capture (if root)
|
||||
// - control plane using webpush messaging
|
||||
// - webRTC and H2 for mesh communication
|
||||
// - convert from H2/H1, based on local port config.
|
||||
//
|
||||
// Extras:
|
||||
// - SOCKS and PROXY
|
||||
//
|
||||
// This does not include lwIP, which is now only used with AndroidVPN in
|
||||
// JNI mode.
|
||||
func main() {
|
||||
// Load configs from the current dir and var/lib/dmesh, or env variables
|
||||
// Writes to current dir.
|
||||
config := ug.NewConf("./", "./var/lib/dmesh")
|
||||
config := ugatesvc.NewConf("./", "./var/lib/dmesh")
|
||||
|
||||
//
|
||||
// Start a Gate. Basic H2 and H2R services enabled.
|
||||
ug := ug.NewGate(&net.Dialer{}, nil, nil, config)
|
||||
ug := ugatesvc.NewGate(&net.Dialer{}, nil, nil, config)
|
||||
|
||||
// Initialize the messaging.
|
||||
msgs.DefaultMux.Auth = ug.Auth
|
||||
|
||||
// Discover local nodes using multicast UDP
|
||||
localgw := local.NewLocal(ug, ug.Auth)
|
||||
local.ListenUDP(localgw)
|
||||
ug.Mux.HandleFunc("/dmesh/ll/if", localgw.HttpGetLLIf)
|
||||
sf := []startFunc{}
|
||||
if initHooks != nil {
|
||||
for _, h := range initHooks {
|
||||
s := h(ug)
|
||||
if s != nil {
|
||||
sf = append(sf, s)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Init DNS capture and server
|
||||
dnss, _ := dns.NewDmDns(5223)
|
||||
//GW. = dnss
|
||||
net.DefaultResolver.PreferGo = true
|
||||
net.DefaultResolver.Dial = dns.DNSDialer(5223)
|
||||
|
||||
// Init Iptables capture (off by default - android doesn't like it)
|
||||
// UDP Gate is used with TProxy and lwIP.
|
||||
udpNat := udp.NewUDPGate(dnss, dnss)
|
||||
udpNat.InitMux(ug.Mux)
|
||||
|
||||
hproxy := ugatesvc.NewHTTPProxy(ug)
|
||||
hproxy.HttpProxyCapture(fmt.Sprintf("127.0.0.1:%d", ug.Config.BasePort+ugate.PORT_HTTP_PROXY))
|
||||
|
||||
// Init WebRTC port
|
||||
|
||||
go dnss.Serve()
|
||||
|
||||
for _, h := range sf {
|
||||
go h(ug)
|
||||
}
|
||||
|
||||
log.Println("Started: ", ug.Auth.ID)
|
||||
select {}
|
||||
|
||||
11
cmd/ugate/ugate_dns.go
Normal file
11
cmd/ugate/ugate_dns.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/costinm/ugate/pkg/ugatesvc"
|
||||
)
|
||||
|
||||
func init() {
|
||||
initHooks = append(initHooks, func(ug *ugatesvc.UGate) startFunc{
|
||||
return nil
|
||||
})
|
||||
}
|
||||
18
cmd/ugate/ugate_iptables.go
Normal file
18
cmd/ugate/ugate_iptables.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/costinm/ugate"
|
||||
"github.com/costinm/ugate/pkg/iptables"
|
||||
"github.com/costinm/ugate/pkg/ugatesvc"
|
||||
)
|
||||
|
||||
func init() {
|
||||
initHooks = append(initHooks, func(ug *ugatesvc.UGate) startFunc {
|
||||
// Init Iptables capture (off by default - android doesn't like it)
|
||||
iptables.IptablesCapture(ug, fmt.Sprintf("0.0.0.0:%d", ug.Config.BasePort+ugate.PORT_IPTABLES), false)
|
||||
iptables.IptablesCapture(ug, fmt.Sprintf("0.0.0.0:%d", ug.Config.BasePort+ugate.PORT_IPTABLES_IN), true)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
17
cmd/ugate/ugate_local.go
Normal file
17
cmd/ugate/ugate_local.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/costinm/ugate/pkg/local"
|
||||
"github.com/costinm/ugate/pkg/ugatesvc"
|
||||
)
|
||||
|
||||
func init() {
|
||||
initHooks = append(initHooks, func(ug *ugatesvc.UGate) startFunc {
|
||||
// Discover local nodes using multicast UDP
|
||||
localgw := local.NewLocal(ug, ug.Auth)
|
||||
local.ListenUDP(localgw)
|
||||
go localgw.PeriodicThread()
|
||||
ug.Mux.HandleFunc("/dmesh/ll/if", localgw.HttpGetLLIf)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
13
cmd/ugate/ugate_webpush.go
Normal file
13
cmd/ugate/ugate_webpush.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/costinm/ugate/pkg/ugatesvc"
|
||||
"github.com/costinm/ugate/webpush"
|
||||
)
|
||||
|
||||
func init() {
|
||||
initHooks = append(initHooks, func(gate *ugatesvc.UGate) startFunc {
|
||||
webpush.InitMux(webpush.DefaultMux, gate.Mux, gate.Auth)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
"github.com/costinm/ugate/pkg/ugatesvc"
|
||||
)
|
||||
|
||||
var initHooks []func(gate *ugatesvc.UGate)
|
||||
|
||||
// Minimal uGate - not using any optional package.
|
||||
// Used to determine the 'base' size and cost of various options.
|
||||
//
|
||||
@@ -26,6 +28,12 @@ func main() {
|
||||
// Start a Gate. Basic H2 and H2R services enabled.
|
||||
ug := ugatesvc.NewGate(&net.Dialer{}, nil, cfg, config)
|
||||
|
||||
if initHooks != nil {
|
||||
for _, h := range initHooks {
|
||||
h(ug)
|
||||
}
|
||||
}
|
||||
|
||||
// direct TCP connect to local iperf3 and fortio (or HTTP on default port)
|
||||
ug.Add(&ugate.Listener{
|
||||
Address: ":12011",
|
||||
|
||||
@@ -2,15 +2,74 @@ package iptables
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/costinm/ugate"
|
||||
"github.com/costinm/ugate/pkg/ugatesvc"
|
||||
)
|
||||
|
||||
//
|
||||
func IptablesCapture(ug *ugatesvc.UGate, addr string, in bool) error {
|
||||
// For http proxy we need a dedicated plain HTTP port
|
||||
nl, err := net.Listen("tcp", addr)
|
||||
if err != nil {
|
||||
log.Println("Failed to listen", err)
|
||||
return err
|
||||
}
|
||||
for {
|
||||
remoteConn, err := nl.Accept()
|
||||
ugate.VarzAccepted.Add(1)
|
||||
if ne, ok := err.(net.Error); ok {
|
||||
ugate.VarzAcceptErr.Add(1)
|
||||
if ne.Temporary() {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
continue
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
log.Println("Accept error, closing iptables listener ", err)
|
||||
return err
|
||||
}
|
||||
go handleAcceptedConn(ug, remoteConn, in)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Mirroring handleAcceptedConn in UGate
|
||||
func handleAcceptedConn(ug *ugatesvc.UGate, acceptedCon net.Conn, in bool) {
|
||||
bconn := ugate.GetConn(acceptedCon)
|
||||
ug.TrackStreamIN(bconn.Meta())
|
||||
defer ug.OnAcceptDone(bconn)
|
||||
str := bconn.Meta()
|
||||
|
||||
//case ugate.ProtoIPTablesIn:
|
||||
// // iptables is replacing the conn - process before creating the buffer
|
||||
// DestAddr is also set as a sideeffect
|
||||
str.Dest, str.ReadErr = SniffIptables(str)
|
||||
|
||||
if str.ReadErr != nil {
|
||||
return
|
||||
}
|
||||
|
||||
cfg := ug.FindCfgIptablesIn(bconn)
|
||||
if cfg.ForwardTo != "" {
|
||||
str.Dest = cfg.ForwardTo
|
||||
}
|
||||
str.Listener = cfg
|
||||
str.Type = cfg.Protocol
|
||||
|
||||
if !in {
|
||||
str.Egress = true
|
||||
}
|
||||
|
||||
str.ReadErr = ug.HandleStream(str)
|
||||
}
|
||||
|
||||
// Status:
|
||||
// - TCP capture with redirect works
|
||||
@@ -27,7 +86,7 @@ import (
|
||||
// https://github.com/ryanchapman/go-any-proxy/blob/master/any_proxy.go,
|
||||
// and other examples.
|
||||
// Based on REDIRECT.
|
||||
func SniffIptables(str *ugate.Stream, proto string) (string, error) {
|
||||
func SniffIptables(str *ugate.Stream) (string, error) {
|
||||
if _, ok := str.Out.(*net.TCPConn); !ok {
|
||||
return "", errors.New("invalid connection for iptbles")
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ const (
|
||||
extensionServerName uint16 = 0
|
||||
)
|
||||
|
||||
// Expecting SNI
|
||||
func SniffSNI(acc *ugate.RawConn) error {
|
||||
acc.Sniff()
|
||||
|
||||
@@ -72,6 +73,7 @@ func SniffSNI(acc *ugate.RawConn) error {
|
||||
|
||||
rlen := int(buf[3])<<8 | int(buf[4])
|
||||
if rlen > 4096 {
|
||||
log.Println("RLen ", rlen)
|
||||
return sniErr
|
||||
}
|
||||
|
||||
@@ -94,6 +96,7 @@ func SniffSNI(acc *ugate.RawConn) error {
|
||||
chLen := end - 5
|
||||
|
||||
if chLen < 38 {
|
||||
log.Println("chLen ", chLen)
|
||||
return sniErr
|
||||
}
|
||||
|
||||
@@ -104,6 +107,7 @@ func SniffSNI(acc *ugate.RawConn) error {
|
||||
|
||||
sessionIdLen := int(clientHello[38])
|
||||
if sessionIdLen > 32 || chLen < 39+sessionIdLen {
|
||||
log.Println("sLen ", sessionIdLen)
|
||||
return sniErr
|
||||
}
|
||||
m.sessionId = clientHello[39 : 39+sessionIdLen]
|
||||
|
||||
@@ -136,7 +136,6 @@ type UdpNat struct {
|
||||
type UDPGateConfig struct {
|
||||
DNS ugate.UDPHandler
|
||||
HostResolver ugate.HostResolver
|
||||
|
||||
}
|
||||
|
||||
type UDPGate struct {
|
||||
|
||||
@@ -20,7 +20,7 @@ import (
|
||||
// Called at the end of the connection handling. After this point
|
||||
// nothing should use or refer to the connection, both proxy directions
|
||||
// should already be closed for write or fully closed.
|
||||
func (ug *UGate) onAcceptDone(rc ugate.MetaConn) {
|
||||
func (ug *UGate) OnAcceptDone(rc ugate.MetaConn) {
|
||||
str := rc.Meta()
|
||||
ug.m.Lock()
|
||||
delete(ug.ActiveTcp, str.StreamId)
|
||||
@@ -85,7 +85,7 @@ func (ug *UGate) onAcceptDone(rc ugate.MetaConn) {
|
||||
|
||||
// Deferred to connection close, only for the raw accepted connection.
|
||||
func (ug *UGate) onAcceptDoneAndRecycle(rc *ugate.RawConn) {
|
||||
ug.onAcceptDone(rc)
|
||||
ug.OnAcceptDone(rc)
|
||||
ugate.BufferedConPool.Put(rc)
|
||||
}
|
||||
|
||||
@@ -121,8 +121,8 @@ func (ug *UGate) onAcceptDoneAndRecycle(rc *ugate.RawConn) {
|
||||
func (ug *UGate) HandleTUN(conn net.Conn, target *net.TCPAddr) error {
|
||||
bconn := ugate.GetConn(conn)
|
||||
bconn.Meta().Egress = true
|
||||
ug.trackStreamIN(bconn.Meta())
|
||||
defer ug.onAcceptDone(bconn)
|
||||
ug.TrackStreamIN(bconn.Meta())
|
||||
defer ug.OnAcceptDone(bconn)
|
||||
|
||||
ra := conn.RemoteAddr()
|
||||
//la := conn.LocalAddr()
|
||||
@@ -139,17 +139,18 @@ func (ug *UGate) HandleTUN(conn net.Conn, target *net.TCPAddr) error {
|
||||
}
|
||||
bconn.Stream.Egress = true
|
||||
|
||||
log.Println("TUN TCP ", bconn.Meta())
|
||||
// TODO: config ? Could be shared with iptables port
|
||||
return ug.handleStream(bconn.Meta())
|
||||
return ug.HandleStream(bconn.Meta())
|
||||
}
|
||||
|
||||
// Handle a virtual (multiplexed) stream, received over
|
||||
// another connection.
|
||||
func (ug *UGate) HandleVirtualIN(bconn ugate.MetaConn) error {
|
||||
ug.trackStreamIN(bconn.Meta())
|
||||
defer ug.onAcceptDone(bconn)
|
||||
ug.TrackStreamIN(bconn.Meta())
|
||||
defer ug.OnAcceptDone(bconn)
|
||||
|
||||
return ug.handleStream(bconn.Meta())
|
||||
return ug.HandleStream(bconn.Meta())
|
||||
}
|
||||
|
||||
// At this point the stream has the metadata:
|
||||
@@ -158,7 +159,7 @@ func (ug *UGate) HandleVirtualIN(bconn ugate.MetaConn) error {
|
||||
// - Headers
|
||||
// - TLS context
|
||||
// - Dest and Listener are set.
|
||||
func (ug *UGate) handleStream(str *ugate.Stream) error {
|
||||
func (ug *UGate) HandleStream(str *ugate.Stream) error {
|
||||
if str.Listener == nil {
|
||||
str.Listener = ug.DefaultListener
|
||||
}
|
||||
@@ -166,7 +167,7 @@ func (ug *UGate) handleStream(str *ugate.Stream) error {
|
||||
|
||||
if cfg.Protocol == ugate.ProtoHTTPS {
|
||||
str.PostDial(str, nil)
|
||||
return ug.h2Handler.Handle(str)
|
||||
return ug.H2Handler.Handle(str)
|
||||
}
|
||||
|
||||
// Config has an in-process handler - not forwarding (or the handler may
|
||||
@@ -182,7 +183,7 @@ func (ug *UGate) handleStream(str *ugate.Stream) error {
|
||||
return ug.dialOut(str)
|
||||
}
|
||||
|
||||
func (ug *UGate) trackStreamIN(s *ugate.Stream) {
|
||||
func (ug *UGate) TrackStreamIN(s *ugate.Stream) {
|
||||
ug.m.Lock()
|
||||
ug.ActiveTcp[s.StreamId] = s
|
||||
ug.m.Unlock()
|
||||
@@ -211,8 +212,8 @@ func (ug *UGate) handleAcceptedConn(l *ugate.Listener, acceptedCon net.Conn) {
|
||||
// Get a buffered stream - this is used for sniffing.
|
||||
// Most common case is TLS, we want the SNI.
|
||||
bconn := ugate.GetConn(acceptedCon)
|
||||
ug.trackStreamIN(bconn.Meta())
|
||||
defer ug.onAcceptDone(bconn)
|
||||
ug.TrackStreamIN(bconn.Meta())
|
||||
defer ug.OnAcceptDone(bconn)
|
||||
str := bconn.Meta()
|
||||
|
||||
// Special protocols, muxed on a single port - will extract real
|
||||
@@ -222,25 +223,24 @@ func (ug *UGate) handleAcceptedConn(l *ugate.Listener, acceptedCon net.Conn) {
|
||||
switch cfg.Protocol {
|
||||
// TODO: costin: does not compile on android gomobile, missing syscall.
|
||||
// remove dep, reverse it.
|
||||
//case ugate.ProtoIPTablesIn:
|
||||
// // iptables is replacing the conn - process before creating the buffer
|
||||
// str.Dest, str.ReadErr = iptables.SniffIptables(str, cfg.Protocol)
|
||||
// cfg = ug.findCfgIptablesIn(bconn)
|
||||
//case ugate.ProtoIPTables:
|
||||
// str.Dest, str.ReadErr = iptables.SniffIptables(str, cfg.Protocol)
|
||||
// str.Egress = true
|
||||
case ugate.ProtoSocks:
|
||||
str.Egress = true
|
||||
str.ReadErr = socks.ReadSocksHeader(bconn)
|
||||
case ugate.ProtoHTTP:
|
||||
str.ReadErr = ug.h2Handler.handleHTTPListener(l, bconn)
|
||||
str.ReadErr = ug.H2Handler.handleHTTPListener(l, bconn)
|
||||
return
|
||||
case ugate.ProtoHTTPS:
|
||||
tlsTerm = true
|
||||
// Used to present the right cert
|
||||
str.ReadErr = sni.SniffSNI(bconn)
|
||||
if str.ReadErr != nil {
|
||||
log.Println("XXX Failed to snif SNI", str.ReadErr)
|
||||
}
|
||||
case ugate.ProtoTLS:
|
||||
str.ReadErr = sni.SniffSNI(bconn)
|
||||
if str.ReadErr != nil {
|
||||
log.Println("XXX Failed to snif SNI in TLS", str.ReadErr, l.Address, l.Protocol, bconn.Meta())
|
||||
}
|
||||
if str.Dest == "" {
|
||||
// No destination - terminate here
|
||||
// TODO: also if dest hostname == local name or VIP or ID
|
||||
@@ -280,7 +280,7 @@ func (ug *UGate) handleAcceptedConn(l *ugate.Listener, acceptedCon net.Conn) {
|
||||
tlsOrOrigStr = tc.Meta()
|
||||
}
|
||||
|
||||
str.ReadErr = ug.handleStream(tlsOrOrigStr)
|
||||
str.ReadErr = ug.HandleStream(tlsOrOrigStr)
|
||||
}
|
||||
|
||||
// Auto-detect protocol on the wire, so routing info can be
|
||||
|
||||
@@ -135,7 +135,7 @@ func (t *H2Transport) GetClientConn(req *http.Request, addr string) (*http2.Clie
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cc, err := t.ug.h2Handler.h2t.NewClientConn(tc)
|
||||
cc, err := t.ug.H2Handler.h2t.NewClientConn(tc)
|
||||
|
||||
return cc, err
|
||||
}
|
||||
|
||||
@@ -67,6 +67,7 @@ func NewH2Transport(ug *UGate) (*H2Transport, error) {
|
||||
}
|
||||
|
||||
// UpdateReverseAccept updates the upstream accept connections, based on config.
|
||||
// Should be called when the config changes
|
||||
func (t *H2Transport) UpdateReverseAccept() {
|
||||
for addr, key := range t.ug.Config.H2R {
|
||||
t.maintainRemoteAccept(addr, key)
|
||||
@@ -147,6 +148,12 @@ func (l *H2Transport) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// HTTP/1.1
|
||||
if r.Method == "CONNECT" {
|
||||
// WS or HTTP Proxy
|
||||
}
|
||||
|
||||
|
||||
//if r.ProtoMajor > 1 {
|
||||
if len(parts) > 2 {
|
||||
if parts[1] == "h2r" {
|
||||
@@ -180,11 +187,6 @@ func (l *H2Transport) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
// HTTP/1.1
|
||||
if r.Method == "CONNECT" {
|
||||
// WS or HTTP Proxy
|
||||
}
|
||||
|
||||
if strings.HasPrefix(r.RequestURI, "/ws") {
|
||||
|
||||
} else {
|
||||
|
||||
152
pkg/ugatesvc/httpproxy_capture.go
Normal file
152
pkg/ugatesvc/httpproxy_capture.go
Normal file
@@ -0,0 +1,152 @@
|
||||
package ugatesvc
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/costinm/ugate"
|
||||
)
|
||||
|
||||
// Used for HTTP_PROXY=localhost:port, to intercept outbound traffic using http proxy protocol.
|
||||
// CONNECT too.
|
||||
|
||||
// Experimental, not the main capture mode - TUN and SOCKS should be used if possible.
|
||||
|
||||
// HTTPGate handles HTTP requests
|
||||
type HTTPGate struct {
|
||||
//Auth *auth.Auth
|
||||
gw *UGate
|
||||
}
|
||||
|
||||
func NewHTTPProxy(gw *UGate) *HTTPGate {
|
||||
return &HTTPGate{
|
||||
gw: gw,
|
||||
}
|
||||
}
|
||||
|
||||
// Start listening on the addr, as a HTTP_PROXY
|
||||
// Handles CONNECT and PROXY requests using the gateway
|
||||
// for streams.
|
||||
func (gw *HTTPGate) HttpProxyCapture(addr string) error {
|
||||
// For http proxy we need a dedicated plain HTTP port
|
||||
nl, err := net.Listen("tcp", addr)
|
||||
if err != nil {
|
||||
log.Println("Failed to listen", err)
|
||||
return err
|
||||
}
|
||||
go http.Serve(nl, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == "CONNECT" {
|
||||
gw.handleConnect(w, r)
|
||||
return
|
||||
}
|
||||
// This is a real HTTP proxy
|
||||
if r.URL.IsAbs() {
|
||||
log.Println("HTTPPRX", r.Method, r.Host, r.RemoteAddr, r.URL)
|
||||
gw.captureHttpProxyAbsURL(w, r)
|
||||
return
|
||||
}
|
||||
}))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Http proxy to a configured HTTP host. Hostname to HTTP address explicitly
|
||||
// configured. Also hostnmae to file serving.
|
||||
func (gw *HTTPGate) proxy(w http.ResponseWriter, r *http.Request) bool {
|
||||
// TODO: if host is XXXX.m.SUFFIX -> forward to node.
|
||||
|
||||
host, found := gw.gw.Config.Hosts[r.Host]
|
||||
if !found {
|
||||
return false
|
||||
}
|
||||
if len(host.Addr) > 0 {
|
||||
log.Println("FWDHTTP: ", r.Method, r.Host, r.RemoteAddr, r.URL)
|
||||
gw.gw.H2Handler.ForwardHTTP(w, r, host.Addr)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// WIP: HTTP proxy with absolute address, to a QUIC server (or sidecar)`
|
||||
func (gw *HTTPGate) captureHttpProxyAbsURL(w http.ResponseWriter, r *http.Request) {
|
||||
// HTTP proxy mode - uses the QUIC client to connect to the node
|
||||
// TODO: redirect via VPN, only root VPN can do plaintext requests
|
||||
|
||||
// parse r.URL, follow the same steps as TCP - if mesh use Client/mtls, if VPN set forward to VPN, else use H2 client
|
||||
|
||||
// r.Host is populated from the absolute URL.
|
||||
// Typical headers (curl):
|
||||
// User-Agent, Acept, Proxy-Connection:Keep-Alive
|
||||
|
||||
if gw.proxy(w, r) {
|
||||
return
|
||||
}
|
||||
|
||||
ht := &http.Transport{
|
||||
DialContext: gw.gw.DialContext,
|
||||
}
|
||||
hc := &http.Client{Transport: ht}
|
||||
|
||||
// TODO: use VPN to Dial !!!
|
||||
//
|
||||
resp, err := hc.Transport.RoundTrip(r)
|
||||
if err != nil {
|
||||
log.Println("XXX ", err)
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
origBody := resp.Body
|
||||
defer origBody.Close()
|
||||
CopyResponseHeaders(w.Header(), resp.Header)
|
||||
w.WriteHeader(resp.StatusCode)
|
||||
io.Copy(w, resp.Body)
|
||||
|
||||
log.Println("PHTTP: ", r.URL)
|
||||
|
||||
}
|
||||
|
||||
// WIP: If method is CONNECT - operate in TCP proxy mode. This can be used to proxy
|
||||
// a TCP UdpNat to a mesh node, from localhost or from a net node.
|
||||
// Only used to capture local traffic - should be bound to localhost only, like socks.
|
||||
// It speaks HTTP/1.1, no QUIC
|
||||
func (gw *HTTPGate) handleConnect(w http.ResponseWriter, r *http.Request) {
|
||||
hij, ok := w.(http.Hijacker)
|
||||
if !ok {
|
||||
w.WriteHeader(503)
|
||||
w.Write([]byte("Error - no hijack support"))
|
||||
return
|
||||
}
|
||||
|
||||
host := r.URL.Host
|
||||
if !strings.Contains(host, ":") {
|
||||
host = host + ":443"
|
||||
}
|
||||
|
||||
// TODO: second param may contain unprocessed data.
|
||||
proxyClient, _, e := hij.Hijack()
|
||||
if e != nil {
|
||||
w.WriteHeader(503)
|
||||
w.Write([]byte("Error - no hijack support"))
|
||||
return
|
||||
}
|
||||
|
||||
//ra := proxyClient.RemoteAddr().(*net.TCPAddr)
|
||||
str := ugate.GetConn(proxyClient)
|
||||
defer gw.gw.OnAcceptDone(str)
|
||||
gw.gw.TrackStreamIN(str.Meta())
|
||||
|
||||
str.Stream.Dest = host
|
||||
str.Stream.Egress = true
|
||||
str.PostDialHandler = func(conn net.Conn, err error) {
|
||||
if err != nil {
|
||||
w.WriteHeader(503)
|
||||
w.Write([]byte("Dial error" + err.Error()))
|
||||
return
|
||||
}
|
||||
proxyClient.Write([]byte("HTTP/1.0 200 OK\r\n\r\n"))
|
||||
}
|
||||
// TODO: add sniffing on the outbound
|
||||
|
||||
gw.gw.dialOut(str.Meta())
|
||||
}
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
"github.com/costinm/ugate/pkg/pipe"
|
||||
)
|
||||
|
||||
// After a Stream ( TCP+meta or HTTP ) is accepted, we need to route it based on
|
||||
// After a Stream ( TCP+meta or HTTP ) is accepted/captured, we need to route it based on
|
||||
// the config.
|
||||
//
|
||||
// Use cases:
|
||||
@@ -26,6 +26,8 @@ import (
|
||||
|
||||
var NotFound = errors.New("not found")
|
||||
|
||||
// Primary function for egress streams, after metadata has been parsed.
|
||||
//
|
||||
// Dial the target and proxy to it.
|
||||
// - if Dest is a mesh node, use BTS
|
||||
// - else use TCP proxy.
|
||||
@@ -163,7 +165,7 @@ func (ug *UGate) CreateConn(ctx context.Context, dmn *ugate.DMNode) (error) {
|
||||
return err
|
||||
}
|
||||
|
||||
cc, err := ug.h2Handler.h2t.NewClientConn(lconn)
|
||||
cc, err := ug.H2Handler.h2t.NewClientConn(lconn)
|
||||
if err != nil {
|
||||
nc.Close()
|
||||
return err
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
|
||||
"github.com/costinm/ugate"
|
||||
"github.com/costinm/ugate/pkg/auth"
|
||||
"github.com/costinm/ugate/pkg/msgs"
|
||||
msgs "github.com/costinm/ugate/webpush"
|
||||
)
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ type UGate struct {
|
||||
// template, used for TLS connections and the host ID
|
||||
TLSConfig *tls.Config
|
||||
|
||||
h2Handler *H2Transport
|
||||
H2Handler *H2Transport
|
||||
|
||||
// Direct Nodes by interface address (which is derived from public key). This includes only
|
||||
// directly connected notes - either Wifi on same segment, or VPNs and
|
||||
@@ -85,11 +85,24 @@ func NewGate(d ugate.ContextDialer, a *auth.Auth, cfg *ugate.GateCfg, cs ugate.C
|
||||
}
|
||||
}
|
||||
}
|
||||
if cfg.H2R == nil {
|
||||
cfg.H2R = map[string]string{}
|
||||
}
|
||||
if cfg.Hosts == nil {
|
||||
cfg.Hosts = map[string]*ugate.DMNode{}
|
||||
}
|
||||
if cfg.Listeners == nil {
|
||||
cfg.Listeners = map[string]*ugate.Listener{}
|
||||
}
|
||||
|
||||
if cs != nil {
|
||||
Get(cs, "ugate", cfg)
|
||||
}
|
||||
|
||||
if d == nil {
|
||||
d = &net.Dialer{}
|
||||
}
|
||||
|
||||
if a == nil {
|
||||
a = auth.NewAuth(cs, cfg.Name, cfg.Domain)
|
||||
}
|
||||
@@ -137,9 +150,9 @@ func NewGate(d ugate.ContextDialer, a *auth.Auth, cfg *ugate.GateCfg, cs ugate.C
|
||||
//SessionTicketsDisabled: true,
|
||||
}
|
||||
|
||||
ug.h2Handler, _ = NewH2Transport(ug)
|
||||
ug.H2Handler, _ = NewH2Transport(ug)
|
||||
|
||||
go ug.h2Handler.UpdateReverseAccept()
|
||||
go ug.H2Handler.UpdateReverseAccept()
|
||||
|
||||
ug.Mux.Handle("/debug/", http.DefaultServeMux)
|
||||
ug.Mux.HandleFunc("/dmesh/tcpa", ug.HttpTCP)
|
||||
@@ -159,6 +172,8 @@ func NewGate(d ugate.ContextDialer, a *auth.Auth, cfg *ugate.GateCfg, cs ugate.C
|
||||
ug.Add(t)
|
||||
}
|
||||
|
||||
|
||||
|
||||
return ug
|
||||
}
|
||||
|
||||
@@ -285,10 +300,7 @@ func (ug *UGate) DefaultPorts(base int) error {
|
||||
|
||||
// Egress: iptables and SOCKS5
|
||||
// Not on localhost - redirect changes the port, keeps IP
|
||||
ug.Add(&ugate.Listener{
|
||||
Address: fmt.Sprintf("0.0.0.0:%d", base+ugate.PORT_IPTABLES),
|
||||
Protocol: ugate.ProtoIPTables,
|
||||
})
|
||||
|
||||
ug.Add(&ugate.Listener{
|
||||
Address: fmt.Sprintf("127.0.0.1:%d", base+ugate.PORT_SOCKS),
|
||||
Protocol: ugate.ProtoSocks,
|
||||
@@ -296,6 +308,10 @@ func (ug *UGate) DefaultPorts(base int) error {
|
||||
// TODO: add HTTP CONNECT for egress.
|
||||
|
||||
// Ingress: iptables ( capture all incoming )
|
||||
ug.Add(&ugate.Listener{
|
||||
Address: fmt.Sprintf("0.0.0.0:%d", base+ugate.PORT_IPTABLES),
|
||||
Protocol: ugate.ProtoIPTables,
|
||||
})
|
||||
ug.Add(&ugate.Listener{
|
||||
Address: fmt.Sprintf("0.0.0.0:%d", base+ugate.PORT_IPTABLES_IN),
|
||||
Protocol: ugate.ProtoIPTablesIn,
|
||||
@@ -312,7 +328,7 @@ func (ug *UGate) DefaultPorts(base int) error {
|
||||
ug.Add(&ugate.Listener{
|
||||
Address: fmt.Sprintf("0.0.0.0:%d", base+ugate.PORT_HTTPS),
|
||||
Protocol: ugate.ProtoHTTPS,
|
||||
Handler: ug.h2Handler,
|
||||
Handler: ug.H2Handler,
|
||||
})
|
||||
go func() {
|
||||
err := http.ListenAndServe(fmt.Sprintf(":%d", base), ug.Mux)
|
||||
@@ -324,7 +340,9 @@ func (ug *UGate) DefaultPorts(base int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ug *UGate) findCfgIptablesIn(bconn ugate.MetaConn) *ugate.Listener {
|
||||
// Based on the port in the Dest, find the Listener config.
|
||||
// Used when the dest IP:port is extracted from the metadata
|
||||
func (ug *UGate) FindCfgIptablesIn(bconn ugate.MetaConn) *ugate.Listener {
|
||||
m := bconn.Meta()
|
||||
_, p, _ := net.SplitHostPort(m.Dest)
|
||||
l := ug.Config.Listeners["-:"+p]
|
||||
|
||||
@@ -197,7 +197,7 @@ func TestSrv(t *testing.T) {
|
||||
// This is a H2 request that is forwarded to a stream.
|
||||
p := pipe.New()
|
||||
r, _ := http.NewRequest("POST", "https://127.0.0.1:6107/dm/"+"127.0.0.1:6112", p)
|
||||
res, err := ag.h2Handler.RoundTrip(r)
|
||||
res, err := ag.H2Handler.RoundTrip(r)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -214,13 +214,13 @@ func TestSrv(t *testing.T) {
|
||||
ag.Config.H2R = map[string]string{
|
||||
"127.0.0.1:6107": "",
|
||||
}
|
||||
ag.h2Handler.UpdateReverseAccept()
|
||||
ag.H2Handler.UpdateReverseAccept()
|
||||
// Connecting to Bob's gateway (from c). Request should go to Alice.
|
||||
//
|
||||
p := pipe.New()
|
||||
r, _ := http.NewRequest("POST",
|
||||
"https://127.0.0.1:6107/dm/"+ag.Auth.ID, p)
|
||||
res, err := cg.h2Handler.RoundTrip(r)
|
||||
res, err := cg.H2Handler.RoundTrip(r)
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -235,8 +235,8 @@ func TestSrv(t *testing.T) {
|
||||
|
||||
ag.Config.H2R = map[string]string{
|
||||
}
|
||||
ag.h2Handler.UpdateReverseAccept()
|
||||
if len(ag.h2Handler.reverse) > 0 {
|
||||
ag.H2Handler.UpdateReverseAccept()
|
||||
if len(ag.H2Handler.reverse) > 0 {
|
||||
t.Error("Failed to disconnect")
|
||||
}
|
||||
})
|
||||
|
||||
5
ugate.go
5
ugate.go
@@ -76,7 +76,12 @@ const (
|
||||
PORT_IPTABLES = 1
|
||||
PORT_IPTABLES_IN = 6
|
||||
PORT_SOCKS = 9
|
||||
// SNI and HTTP could share the same port - would also
|
||||
// reduce missconfig risks
|
||||
PORT_HTTP_PROXY = 2
|
||||
PORT_SNI = 3
|
||||
|
||||
// H2, HTTPS, H2R
|
||||
PORT_HTTPS = 7
|
||||
)
|
||||
|
||||
|
||||
@@ -70,8 +70,11 @@ func NewMux() *Mux {
|
||||
|
||||
var DefaultMux = NewMux()
|
||||
|
||||
func InitMux(mux *Mux, auth *auth.Auth) {
|
||||
func InitMux(mux *Mux, hmux *http.ServeMux, auth *auth.Auth) {
|
||||
mux.Auth = auth
|
||||
hmux.HandleFunc("/push/", DefaultMux.HTTPHandlerWebpush)
|
||||
hmux.HandleFunc("/subscribe", SubscribeHandler)
|
||||
hmux.HandleFunc("/s/", HTTPHandlerSend)
|
||||
}
|
||||
|
||||
// Send a message to the default mux. Will serialize the event and save it for debugging.
|
||||
|
||||
Reference in New Issue
Block a user