feature: reply proxy info to client

This commit is contained in:
ICKelin
2021-06-05 16:36:28 +08:00
parent c673f0eb68
commit 2177076e01
9 changed files with 88 additions and 43 deletions

View File

@@ -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:
@@ -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"

View File

@@ -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 {
@@ -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 {

View File

@@ -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 {

View File

@@ -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 {
@@ -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{
@@ -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)

View File

@@ -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) {}

View File

@@ -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 {
@@ -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 {
@@ -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) {

View File

@@ -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{
@@ -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{}) {

View File

@@ -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{})
@@ -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) {

View File

@@ -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) {