Skip to content

Commit

Permalink
feature: reply proxy info to client
Browse files Browse the repository at this point in the history
  • Loading branch information
ICKelin committed Jun 5, 2021
1 parent c673f0e commit 2177076
Show file tree
Hide file tree
Showing 9 changed files with 88 additions and 43 deletions.
13 changes: 4 additions & 9 deletions etc/opennotr.yaml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
serverAddr: "demo.notr.tech:10100"
key: "client server exchange key"
key: "http://www.notr.tech"
forwards:
- protocol: tcp
ports:
2221: 2222
0: 2222

- protocol: udp
ports:
531: 53
0: 53

- protocol: http
ports:
Expand All @@ -20,9 +20,4 @@ forwards:
- protocol: h2c
ports:
0: 50052

- protocol: dummy
ports:
0: 0
rawConfig:
"this is a test config pass to dummy plugin"

13 changes: 10 additions & 3 deletions internal/proto/cs.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ type C2SHeartbeat struct{}
type C2SAuth struct {
Key string `json:"key" yaml:"key"`
Domain string `json:"domain" yaml:"domain"`
Forward []ForwardItem `json:"forwards" yaml:"forwards"`
Forward []ForwardItem `json:"forwards" yaml:"forwards"` // request forwards, not real, it depends on opennotrd
}

type ForwardItem struct {
Expand All @@ -43,8 +43,15 @@ type ForwardItem struct {
}

type S2CAuth struct {
Domain string `json:"domain"` // 分配域名
Vip string `json:"vip"` // 分配虚拟ip地址
Domain string `json:"domain"` // uniq domain for opennotr
Vip string `json:"vip"` // vip for opennotr
ProxyInfos []*ProxyTuple `json:"proxyInfos"` // real proxy table
}

type ProxyTuple struct {
Protocol string
FromPort string
ToPort string
}

type ProxyProtocol struct {
Expand Down
7 changes: 7 additions & 0 deletions opennotr/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,13 @@ func (c *Client) Run() {
log.Println("connect success")
log.Println("vhost:", auth.Vip)
log.Println("domain:", auth.Domain)
for _, item := range auth.ProxyInfos {
fromaddr := fmt.Sprintf("%s:%s", auth.Domain, item.FromPort)
if len(item.FromPort) == 0 {
fromaddr = auth.Domain
}
log.Printf("%s://%s => 127.0.0.1:%s\n", item.Protocol, fromaddr, item.ToPort)
}

mux, err := smux.Client(conn, nil)
if err != nil {
Expand Down
31 changes: 19 additions & 12 deletions opennotrd/core/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,17 +98,6 @@ func (s *Server) onConn(conn net.Conn) {
return
}

reply := &proto.S2CAuth{
Vip: vip,
Domain: auth.Domain,
}

err = proto.WriteJSON(conn, proto.CmdAuth, reply)
if err != nil {
logs.Error("write json fail: %v", err)
return
}

// dynamic dns, write domain=>ip map to etcd
// coredns will read records from etcd and reply to dns client
if s.resolver != nil {
Expand All @@ -128,6 +117,7 @@ func (s *Server) onConn(conn net.Conn) {
// 2. for to address, we use $vip:$localPort
// the vip is the virtual lan ip address
// Domain is only use for restyproxy
proxyInfos := make([]*proto.ProxyTuple, 0)
for _, forward := range auth.Forward {
for publicPort, localPort := range forward.Ports {
item := &plugin.PluginMeta{
Expand All @@ -139,15 +129,32 @@ func (s *Server) onConn(conn net.Conn) {
Ctx: forward.RawConfig,
}

err = s.pluginMgr.AddProxy(item)
p, err := s.pluginMgr.AddProxy(item)
if err != nil {
logs.Error("add proxy fail: %v", err)
return
}
proxyInfos = append(proxyInfos, &proto.ProxyTuple{
Protocol: forward.Protocol,
FromPort: p.FromPort,
ToPort: p.ToPort,
})
defer s.pluginMgr.DelProxy(item)
}
}

reply := &proto.S2CAuth{
Vip: vip,
Domain: auth.Domain,
ProxyInfos: proxyInfos,
}

err = proto.WriteJSON(conn, proto.CmdAuth, reply)
if err != nil {
logs.Error("write json fail: %v", err)
return
}

mux, err := smux.Server(conn, nil)
if err != nil {
logs.Error("smux server fail:%v", err)
Expand Down
4 changes: 2 additions & 2 deletions opennotrd/plugin/dummy/dummy.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ func (d *DummyPlugin) Setup(cfg json.RawMessage) error {
return nil
}

func (d *DummyPlugin) RunProxy(meta *plugin.PluginMeta) error {
func (d *DummyPlugin) RunProxy(meta *plugin.PluginMeta) (*plugin.ProxyTuple, error) {
logs.Info("dummy plugin client config: %v", meta.Ctx)
return nil
return &plugin.ProxyTuple{}, nil
}

func (d *DummyPlugin) StopProxy(meta *plugin.PluginMeta) {}
21 changes: 14 additions & 7 deletions opennotrd/plugin/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ var pluginMgr = &PluginManager{
plugins: make(map[string]IPlugin),
}

// ProxyTuple defineds plugins real proxy address
type ProxyTuple struct {
Protocol string
FromPort string
ToPort string
}

// PluginMeta defineds data that the plugins needs
// these members are filled by server.go
type PluginMeta struct {
Expand Down Expand Up @@ -58,7 +65,7 @@ type IPlugin interface {
StopProxy(item *PluginMeta)

// Run a proxy, it may be called by client's connection established
RunProxy(item *PluginMeta) error
RunProxy(item *PluginMeta) (*ProxyTuple, error)
}

type PluginManager struct {
Expand Down Expand Up @@ -103,26 +110,26 @@ func Setup(plugins map[string]string) error {
return nil
}

func (p *PluginManager) AddProxy(item *PluginMeta) error {
func (p *PluginManager) AddProxy(item *PluginMeta) (*ProxyTuple, error) {
p.mu.Lock()
defer p.mu.Unlock()
key := item.identify()
if _, ok := p.routes[key]; ok {
return fmt.Errorf("port %s is in used", key)
return nil, fmt.Errorf("port %s is in used", key)
}

plug, ok := p.plugins[item.Protocol]
if !ok {
return fmt.Errorf("proxy %s not register", item.Protocol)
return nil, fmt.Errorf("proxy %s not register", item.Protocol)
}

err := plug.RunProxy(item)
tuple, err := plug.RunProxy(item)
if err != nil {
logs.Error("run proxy fail: %v", err)
return err
return nil, err
}
p.routes[key] = item
return nil
return tuple, nil
}

func (p *PluginManager) DelProxy(item *PluginMeta) {
Expand Down
11 changes: 8 additions & 3 deletions opennotrd/plugin/restyproxy/restyproxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,10 @@ func (p *RestyProxy) StopProxy(item *plugin.PluginMeta) {
p.sendDeleteReq(item.Domain, item.Protocol)
}

func (p *RestyProxy) RunProxy(item *plugin.PluginMeta) error {
func (p *RestyProxy) RunProxy(item *plugin.PluginMeta) (*plugin.ProxyTuple, error) {
vip, port, err := net.SplitHostPort(item.To)
if err != nil {
return err
return nil, err
}

req := &AddUpstreamBody{
Expand All @@ -64,7 +64,12 @@ func (p *RestyProxy) RunProxy(item *plugin.PluginMeta) error {
}

go p.sendPostReq(req)
return nil

_, toPort, _ := net.SplitHostPort(item.To)
return &plugin.ProxyTuple{
Protocol: item.Protocol,
ToPort: toPort,
}, nil
}

func (p *RestyProxy) sendPostReq(body interface{}) {
Expand Down
15 changes: 12 additions & 3 deletions opennotrd/plugin/tcpproxy/tcpproxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@ func (t *TCPProxy) StopProxy(item *plugin.PluginMeta) {
}
}

func (t *TCPProxy) RunProxy(item *plugin.PluginMeta) error {
// RunProxy runs a tcp server and proxy to item.To
// RunProxy may change item.From address to the real listenner address
func (t *TCPProxy) RunProxy(item *plugin.PluginMeta) (*plugin.ProxyTuple, error) {
from, to := item.From, item.To
lis, err := net.Listen("tcp", from)
if err != nil {
return err
return nil, err
}

fin := make(chan struct{})
Expand Down Expand Up @@ -73,7 +75,14 @@ func (t *TCPProxy) RunProxy(item *plugin.PluginMeta) error {
}
}()

return nil
_, fromPort, _ := net.SplitHostPort(lis.Addr().String())
_, toPort, _ := net.SplitHostPort(item.To)

return &plugin.ProxyTuple{
Protocol: item.Protocol,
FromPort: fromPort,
ToPort: toPort,
}, nil
}

func (t *TCPProxy) doProxy(conn net.Conn, to string) {
Expand Down
16 changes: 12 additions & 4 deletions opennotrd/plugin/udpproxy/udpproxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,20 +48,28 @@ func (p *UDPProxy) StopProxy(item *plugin.PluginMeta) {
}
}

func (p *UDPProxy) RunProxy(item *plugin.PluginMeta) error {
func (p *UDPProxy) RunProxy(item *plugin.PluginMeta) (*plugin.ProxyTuple, error) {
from := item.From
laddr, err := net.ResolveUDPAddr("udp", from)
if err != nil {
return err
return nil, err
}

lis, err := net.ListenUDP("udp", laddr)
if err != nil {
return err
return nil, err
}

go p.doProxy(lis, item)
return nil

_, fromPort, _ := net.SplitHostPort(lis.LocalAddr().String())
_, toPort, _ := net.SplitHostPort(item.To)

return &plugin.ProxyTuple{
Protocol: item.Protocol,
FromPort: fromPort,
ToPort: toPort,
}, nil
}

func (p *UDPProxy) doProxy(lis *net.UDPConn, item *plugin.PluginMeta) {
Expand Down

0 comments on commit 2177076

Please sign in to comment.