mirror of
https://gitee.com/IrisVega/frp.git
synced 2024-11-01 22:31:29 +08:00
add real ip test
This commit is contained in:
parent
fe4e9b55f3
commit
a51e221db3
@ -1,6 +1,6 @@
|
|||||||
version: 2
|
version: 2
|
||||||
jobs:
|
jobs:
|
||||||
go1.16:
|
go-version-latest:
|
||||||
docker:
|
docker:
|
||||||
- image: circleci/golang:1.16-node
|
- image: circleci/golang:1.16-node
|
||||||
working_directory: /go/src/github.com/fatedier/frp
|
working_directory: /go/src/github.com/fatedier/frp
|
||||||
@ -8,7 +8,7 @@ jobs:
|
|||||||
- checkout
|
- checkout
|
||||||
- run: make
|
- run: make
|
||||||
- run: make alltest
|
- run: make alltest
|
||||||
go1.15:
|
go-version-last:
|
||||||
docker:
|
docker:
|
||||||
- image: circleci/golang:1.15-node
|
- image: circleci/golang:1.15-node
|
||||||
working_directory: /go/src/github.com/fatedier/frp
|
working_directory: /go/src/github.com/fatedier/frp
|
||||||
@ -21,5 +21,5 @@ workflows:
|
|||||||
version: 2
|
version: 2
|
||||||
build_and_test:
|
build_and_test:
|
||||||
jobs:
|
jobs:
|
||||||
- go1.16
|
- go-version-latest
|
||||||
- go1.15
|
- go-version-last
|
||||||
|
@ -1,20 +1,152 @@
|
|||||||
package features
|
package features
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/fatedier/frp/pkg/util/log"
|
||||||
"github.com/fatedier/frp/test/e2e/framework"
|
"github.com/fatedier/frp/test/e2e/framework"
|
||||||
|
"github.com/fatedier/frp/test/e2e/framework/consts"
|
||||||
|
"github.com/fatedier/frp/test/e2e/mock/server/httpserver"
|
||||||
|
"github.com/fatedier/frp/test/e2e/mock/server/streamserver"
|
||||||
|
"github.com/fatedier/frp/test/e2e/pkg/request"
|
||||||
|
"github.com/fatedier/frp/test/e2e/pkg/rpc"
|
||||||
|
|
||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
|
pp "github.com/pires/go-proxyproto"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = Describe("[Feature: Real IP]", func() {
|
var _ = Describe("[Feature: Real IP]", func() {
|
||||||
f := framework.NewDefaultFramework()
|
f := framework.NewDefaultFramework()
|
||||||
|
|
||||||
It("HTTP X-Forwarded-For", func() {
|
It("HTTP X-Forwarded-For", func() {
|
||||||
// TODO
|
vhostHTTPPort := f.AllocPort()
|
||||||
_ = f
|
serverConf := consts.DefaultServerConfig + fmt.Sprintf(`
|
||||||
|
vhost_http_port = %d
|
||||||
|
`, vhostHTTPPort)
|
||||||
|
|
||||||
|
localPort := f.AllocPort()
|
||||||
|
localServer := httpserver.New(
|
||||||
|
httpserver.WithBindPort(localPort),
|
||||||
|
httpserver.WithHandler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||||
|
w.Write([]byte(req.Header.Get("X-Forwarded-For")))
|
||||||
|
})),
|
||||||
|
)
|
||||||
|
f.RunServer("", localServer)
|
||||||
|
|
||||||
|
clientConf := consts.DefaultClientConfig
|
||||||
|
clientConf += fmt.Sprintf(`
|
||||||
|
[test]
|
||||||
|
type = http
|
||||||
|
local_port = %d
|
||||||
|
custom_domains = normal.example.com
|
||||||
|
`, localPort)
|
||||||
|
|
||||||
|
f.RunProcesses([]string{serverConf}, []string{clientConf})
|
||||||
|
|
||||||
|
framework.NewRequestExpect(f).Port(vhostHTTPPort).
|
||||||
|
RequestModify(func(r *request.Request) {
|
||||||
|
r.HTTP().HTTPHost("normal.example.com")
|
||||||
|
}).
|
||||||
|
ExpectResp([]byte("127.0.0.1")).
|
||||||
|
Ensure()
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
It("Proxy Protocol", func() {
|
Describe("Proxy Protocol", func() {
|
||||||
// TODO
|
It("TCP", func() {
|
||||||
|
serverConf := consts.DefaultServerConfig
|
||||||
|
clientConf := consts.DefaultClientConfig
|
||||||
|
|
||||||
|
localPort := f.AllocPort()
|
||||||
|
localServer := streamserver.New(streamserver.TCP, streamserver.WithBindPort(localPort),
|
||||||
|
streamserver.WithCustomHandler(func(c net.Conn) {
|
||||||
|
defer c.Close()
|
||||||
|
rd := bufio.NewReader(c)
|
||||||
|
ppHeader, err := pp.Read(rd)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("read proxy protocol error: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
if _, err := rpc.ReadBytes(rd); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := []byte(ppHeader.SourceAddr.String())
|
||||||
|
rpc.WriteBytes(c, buf)
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
f.RunServer("", localServer)
|
||||||
|
|
||||||
|
remotePort := f.AllocPort()
|
||||||
|
clientConf += fmt.Sprintf(`
|
||||||
|
[tcp]
|
||||||
|
type = tcp
|
||||||
|
local_port = %d
|
||||||
|
remote_port = %d
|
||||||
|
proxy_protocol_version = v2
|
||||||
|
`, localPort, remotePort)
|
||||||
|
|
||||||
|
f.RunProcesses([]string{serverConf}, []string{clientConf})
|
||||||
|
|
||||||
|
framework.NewRequestExpect(f).Port(remotePort).Ensure(func(resp *request.Response) bool {
|
||||||
|
log.Trace("ProxyProtocol get SourceAddr: %s", string(resp.Content))
|
||||||
|
addr, err := net.ResolveTCPAddr("tcp", string(resp.Content))
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if addr.IP.String() != "127.0.0.1" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
It("HTTP", func() {
|
||||||
|
vhostHTTPPort := f.AllocPort()
|
||||||
|
serverConf := consts.DefaultServerConfig + fmt.Sprintf(`
|
||||||
|
vhost_http_port = %d
|
||||||
|
`, vhostHTTPPort)
|
||||||
|
|
||||||
|
clientConf := consts.DefaultClientConfig
|
||||||
|
|
||||||
|
localPort := f.AllocPort()
|
||||||
|
var srcAddrRecord string
|
||||||
|
localServer := streamserver.New(streamserver.TCP, streamserver.WithBindPort(localPort),
|
||||||
|
streamserver.WithCustomHandler(func(c net.Conn) {
|
||||||
|
defer c.Close()
|
||||||
|
rd := bufio.NewReader(c)
|
||||||
|
ppHeader, err := pp.Read(rd)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("read proxy protocol error: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
srcAddrRecord = ppHeader.SourceAddr.String()
|
||||||
|
}))
|
||||||
|
f.RunServer("", localServer)
|
||||||
|
|
||||||
|
clientConf += fmt.Sprintf(`
|
||||||
|
[test]
|
||||||
|
type = http
|
||||||
|
local_port = %d
|
||||||
|
custom_domains = normal.example.com
|
||||||
|
proxy_protocol_version = v2
|
||||||
|
`, localPort)
|
||||||
|
|
||||||
|
f.RunProcesses([]string{serverConf}, []string{clientConf})
|
||||||
|
|
||||||
|
framework.NewRequestExpect(f).Port(vhostHTTPPort).RequestModify(func(r *request.Request) {
|
||||||
|
r.HTTP().HTTPHost("normal.example.com")
|
||||||
|
}).Ensure(framework.ExpectResponseCode(404))
|
||||||
|
|
||||||
|
log.Trace("ProxyProtocol get SourceAddr: %s", srcAddrRecord)
|
||||||
|
addr, err := net.ResolveTCPAddr("tcp", srcAddrRecord)
|
||||||
|
framework.ExpectNoError(err, srcAddrRecord)
|
||||||
|
framework.ExpectEqualValues("127.0.0.1", addr.IP.String())
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -17,7 +17,11 @@ func SpecifiedHTTPBodyHandler(body []byte) http.HandlerFunc {
|
|||||||
|
|
||||||
func ExpectResponseCode(code int) EnsureFunc {
|
func ExpectResponseCode(code int) EnsureFunc {
|
||||||
return func(resp *request.Response) bool {
|
return func(resp *request.Response) bool {
|
||||||
return resp.Code == code
|
if resp.Code == code {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
flog.Warn("Expect code %d, but got %d", code, resp.Code)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
package streamserver
|
package streamserver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
libnet "github.com/fatedier/frp/pkg/util/net"
|
libnet "github.com/fatedier/frp/pkg/util/net"
|
||||||
@ -22,6 +24,8 @@ type Server struct {
|
|||||||
bindPort int
|
bindPort int
|
||||||
respContent []byte
|
respContent []byte
|
||||||
|
|
||||||
|
handler func(net.Conn)
|
||||||
|
|
||||||
l net.Listener
|
l net.Listener
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,6 +36,7 @@ func New(netType Type, options ...Option) *Server {
|
|||||||
netType: netType,
|
netType: netType,
|
||||||
bindAddr: "127.0.0.1",
|
bindAddr: "127.0.0.1",
|
||||||
}
|
}
|
||||||
|
s.handler = s.handle
|
||||||
|
|
||||||
for _, option := range options {
|
for _, option := range options {
|
||||||
s = option(s)
|
s = option(s)
|
||||||
@ -60,6 +65,13 @@ func WithRespContent(content []byte) Option {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func WithCustomHandler(handler func(net.Conn)) Option {
|
||||||
|
return func(s *Server) *Server {
|
||||||
|
s.handler = handler
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Server) Run() error {
|
func (s *Server) Run() error {
|
||||||
if err := s.initListener(); err != nil {
|
if err := s.initListener(); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -71,7 +83,7 @@ func (s *Server) Run() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
go s.handle(c)
|
go s.handler(c)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
return nil
|
return nil
|
||||||
@ -101,8 +113,12 @@ func (s *Server) initListener() (err error) {
|
|||||||
func (s *Server) handle(c net.Conn) {
|
func (s *Server) handle(c net.Conn) {
|
||||||
defer c.Close()
|
defer c.Close()
|
||||||
|
|
||||||
|
var reader io.Reader = c
|
||||||
|
if s.netType == UDP {
|
||||||
|
reader = bufio.NewReader(c)
|
||||||
|
}
|
||||||
for {
|
for {
|
||||||
buf, err := rpc.ReadBytes(c)
|
buf, err := rpc.ReadBytes(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package request
|
package request
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@ -120,7 +121,7 @@ func (r *Request) Do() (*Response, error) {
|
|||||||
addr := net.JoinHostPort(r.addr, strconv.Itoa(r.port))
|
addr := net.JoinHostPort(r.addr, strconv.Itoa(r.port))
|
||||||
// for protocol http
|
// for protocol http
|
||||||
if r.protocol == "http" {
|
if r.protocol == "http" {
|
||||||
return sendHTTPRequest(r.method, fmt.Sprintf("http://%s%s", addr, r.path),
|
return r.sendHTTPRequest(r.method, fmt.Sprintf("http://%s%s", addr, r.path),
|
||||||
r.host, r.headers, r.proxyURL, r.body)
|
r.host, r.headers, r.proxyURL, r.body)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,7 +152,7 @@ func (r *Request) Do() (*Response, error) {
|
|||||||
if r.timeout > 0 {
|
if r.timeout > 0 {
|
||||||
conn.SetDeadline(time.Now().Add(r.timeout))
|
conn.SetDeadline(time.Now().Add(r.timeout))
|
||||||
}
|
}
|
||||||
buf, err := sendRequestByConn(conn, r.body)
|
buf, err := r.sendRequestByConn(conn, r.body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -164,7 +165,7 @@ type Response struct {
|
|||||||
Content []byte
|
Content []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendHTTPRequest(method, urlstr string, host string, headers map[string]string, proxy string, body []byte) (*Response, error) {
|
func (r *Request) sendHTTPRequest(method, urlstr string, host string, headers map[string]string, proxy string, body []byte) (*Response, error) {
|
||||||
var inBody io.Reader
|
var inBody io.Reader
|
||||||
if len(body) != 0 {
|
if len(body) != 0 {
|
||||||
inBody = bytes.NewReader(body)
|
inBody = bytes.NewReader(body)
|
||||||
@ -210,13 +211,18 @@ func sendHTTPRequest(method, urlstr string, host string, headers map[string]stri
|
|||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendRequestByConn(c net.Conn, content []byte) ([]byte, error) {
|
func (r *Request) sendRequestByConn(c net.Conn, content []byte) ([]byte, error) {
|
||||||
_, err := rpc.WriteBytes(c, content)
|
_, err := rpc.WriteBytes(c, content)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("write error: %v", err)
|
return nil, fmt.Errorf("write error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
buf, err := rpc.ReadBytes(c)
|
var reader io.Reader = c
|
||||||
|
if r.protocol == "udp" {
|
||||||
|
reader = bufio.NewReader(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
buf, err := rpc.ReadBytes(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("read error: %v", err)
|
return nil, fmt.Errorf("read error: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package rpc
|
package rpc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
@ -16,15 +15,12 @@ func WriteBytes(w io.Writer, buf []byte) (int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ReadBytes(r io.Reader) ([]byte, error) {
|
func ReadBytes(r io.Reader) ([]byte, error) {
|
||||||
// To compatible with UDP connection, use bufio reader here to avoid lost conent.
|
|
||||||
rd := bufio.NewReader(r)
|
|
||||||
|
|
||||||
var length int64
|
var length int64
|
||||||
if err := binary.Read(rd, binary.BigEndian, &length); err != nil {
|
if err := binary.Read(r, binary.BigEndian, &length); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
buffer := make([]byte, length)
|
buffer := make([]byte, length)
|
||||||
n, err := io.ReadFull(rd, buffer)
|
n, err := io.ReadFull(r, buffer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user