Browse Source

plugin: new plugin static_file for getting files by http protocol

fatedier 7 years ago
parent
commit
68dfc89bce
4 changed files with 158 additions and 44 deletions
  1. 27 0
      conf/frpc_full.ini
  2. 0 44
      models/plugin/http_proxy.go
  3. 44 0
      models/plugin/plugin.go
  4. 87 0
      models/plugin/static_file.go

+ 27 - 0
conf/frpc_full.ini

@@ -73,6 +73,16 @@ local_port = 22
 # if remote_port is 0, frps will assgin a random port for you
 remote_port = 0
 
+# if you want tp expose multiple ports, add 'range:' prefix to the section name
+# frpc will generate multiple proxies such as 'tcp_port_6010', 'tcp_port_6011' and so on.
+[range:tcp_port]
+type = tcp
+local_ip = 127.0.0.1
+local_port = 6010-6020,6022,6024-6028
+remote_port = 6010-6020,6022,6024-6028
+use_encryption = false
+use_compression = false
+
 [dns]
 type = udp
 local_ip = 114.114.114.114
@@ -81,6 +91,14 @@ remote_port = 6002
 use_encryption = false
 use_compression = false
 
+[range:udp_port]
+type = udp
+local_ip = 127.0.0.1
+local_port = 6010-6020
+remote_port = 6010-6020
+use_encryption = false
+use_compression = false
+
 # Resolve your domain names to [server_addr] so you can use http://web01.yourdomain.com to browse web01 and http://web02.yourdomain.com to browse web02
 [web01]
 type = http
@@ -124,6 +142,15 @@ plugin = http_proxy
 plugin_http_user = abc
 plugin_http_passwd = abc
 
+[plugin_static_file]
+type = tcp
+remote_port = 6005
+plugin = static_file
+plugin_local_path = /var/www/blog
+plugin_strip_prefix = static
+plugin_http_user = abc
+plugin_http_passwd = abc
+
 [secret_tcp]
 # If the type is secret tcp, remote_port is useless
 # Who want to connect local port should deploy another frpc with stcp proxy and role is visitor

+ 0 - 44
models/plugin/http_proxy.go

@@ -17,14 +17,11 @@ package plugin
 import (
 	"bufio"
 	"encoding/base64"
-	"fmt"
 	"io"
 	"net"
 	"net/http"
 	"strings"
-	"sync"
 
-	"github.com/fatedier/frp/utils/errors"
 	frpIo "github.com/fatedier/frp/utils/io"
 	frpNet "github.com/fatedier/frp/utils/net"
 )
@@ -35,47 +32,6 @@ func init() {
 	Register(PluginHttpProxy, NewHttpProxyPlugin)
 }
 
-type Listener struct {
-	conns  chan net.Conn
-	closed bool
-	mu     sync.Mutex
-}
-
-func NewProxyListener() *Listener {
-	return &Listener{
-		conns: make(chan net.Conn, 64),
-	}
-}
-
-func (l *Listener) Accept() (net.Conn, error) {
-	conn, ok := <-l.conns
-	if !ok {
-		return nil, fmt.Errorf("listener closed")
-	}
-	return conn, nil
-}
-
-func (l *Listener) PutConn(conn net.Conn) error {
-	err := errors.PanicToError(func() {
-		l.conns <- conn
-	})
-	return err
-}
-
-func (l *Listener) Close() error {
-	l.mu.Lock()
-	defer l.mu.Unlock()
-	if !l.closed {
-		close(l.conns)
-		l.closed = true
-	}
-	return nil
-}
-
-func (l *Listener) Addr() net.Addr {
-	return (*net.TCPAddr)(nil)
-}
-
 type HttpProxy struct {
 	l          *Listener
 	s          *http.Server

+ 44 - 0
models/plugin/plugin.go

@@ -17,7 +17,10 @@ package plugin
 import (
 	"fmt"
 	"io"
+	"net"
+	"sync"
 
+	"github.com/fatedier/frp/utils/errors"
 	frpNet "github.com/fatedier/frp/utils/net"
 )
 
@@ -45,3 +48,44 @@ type Plugin interface {
 	Handle(conn io.ReadWriteCloser, realConn frpNet.Conn)
 	Close() error
 }
+
+type Listener struct {
+	conns  chan net.Conn
+	closed bool
+	mu     sync.Mutex
+}
+
+func NewProxyListener() *Listener {
+	return &Listener{
+		conns: make(chan net.Conn, 64),
+	}
+}
+
+func (l *Listener) Accept() (net.Conn, error) {
+	conn, ok := <-l.conns
+	if !ok {
+		return nil, fmt.Errorf("listener closed")
+	}
+	return conn, nil
+}
+
+func (l *Listener) PutConn(conn net.Conn) error {
+	err := errors.PanicToError(func() {
+		l.conns <- conn
+	})
+	return err
+}
+
+func (l *Listener) Close() error {
+	l.mu.Lock()
+	defer l.mu.Unlock()
+	if !l.closed {
+		close(l.conns)
+		l.closed = true
+	}
+	return nil
+}
+
+func (l *Listener) Addr() net.Addr {
+	return (*net.TCPAddr)(nil)
+}

+ 87 - 0
models/plugin/static_file.go

@@ -0,0 +1,87 @@
+// Copyright 2018 fatedier, fatedier@gmail.com
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package plugin
+
+import (
+	"io"
+	"net/http"
+
+	"github.com/julienschmidt/httprouter"
+
+	frpNet "github.com/fatedier/frp/utils/net"
+)
+
+const PluginStaticFile = "static_file"
+
+func init() {
+	Register(PluginStaticFile, NewStaticFilePlugin)
+}
+
+type StaticFilePlugin struct {
+	localPath   string
+	stripPrefix string
+	httpUser    string
+	httpPasswd  string
+
+	l *Listener
+	s *http.Server
+}
+
+func NewStaticFilePlugin(params map[string]string) (Plugin, error) {
+	localPath := params["plugin_local_path"]
+	stripPrefix := params["plugin_strip_prefix"]
+	httpUser := params["plugin_http_user"]
+	httpPasswd := params["plugin_http_passwd"]
+
+	listener := NewProxyListener()
+
+	sp := &StaticFilePlugin{
+		localPath:   localPath,
+		stripPrefix: stripPrefix,
+		httpUser:    httpUser,
+		httpPasswd:  httpPasswd,
+
+		l: listener,
+	}
+	var prefix string
+	if stripPrefix != "" {
+		prefix = "/" + stripPrefix + "/"
+	} else {
+		prefix = "/"
+	}
+	router := httprouter.New()
+	router.Handler("GET", prefix+"*filepath", frpNet.MakeHttpGzipHandler(
+		frpNet.NewHttpBasicAuthWraper(http.StripPrefix(prefix, http.FileServer(http.Dir(localPath))), httpUser, httpPasswd)))
+	sp.s = &http.Server{
+		Handler: router,
+	}
+	go sp.s.Serve(listener)
+	return sp, nil
+}
+
+func (sp *StaticFilePlugin) Handle(conn io.ReadWriteCloser, realConn frpNet.Conn) {
+	wrapConn := frpNet.WrapReadWriteCloserToConn(conn, realConn)
+	sp.l.PutConn(wrapConn)
+}
+
+func (sp *StaticFilePlugin) Name() string {
+	return PluginStaticFile
+}
+
+func (sp *StaticFilePlugin) Close() error {
+	sp.s.Close()
+	sp.l.Close()
+	return nil
+}