Wss support (#3)
* added wss support * changed entrypoints in Dockerfiles to include config from .ini files Signed-off-by: Daniel Soifer <daniel.soifer@codefresh.io>
This commit is contained in:
parent
2158253f2e
commit
2384484ed7
@ -18,6 +18,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"io"
|
"io"
|
||||||
|
"math"
|
||||||
"net"
|
"net"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -242,9 +243,21 @@ func (ctl *Control) connectServer() (conn net.Conn, err error) {
|
|||||||
}
|
}
|
||||||
dialOptions := []libdial.DialOption{}
|
dialOptions := []libdial.DialOption{}
|
||||||
protocol := ctl.clientCfg.Protocol
|
protocol := ctl.clientCfg.Protocol
|
||||||
if protocol == "websocket" {
|
var websocketAfterHook *libdial.AfterHook
|
||||||
|
if protocol == "websocket" || protocol == "wss" {
|
||||||
|
if protocol == "wss" {
|
||||||
|
websocketAfterHook = &libdial.AfterHook{
|
||||||
|
Priority: math.MaxUint64, // in case of wss, we first want to make the TLS handshake and then switch protocols from https to wss
|
||||||
|
Hook: frpNet.DialHookWebsocket(true),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
websocketAfterHook = &libdial.AfterHook{
|
||||||
|
Priority: 0, // in case of ws, we first want to switch protocols from http to ws, and only then make the TLS handshake in case TLS is enabled
|
||||||
|
Hook: frpNet.DialHookWebsocket(false),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protocol = "tcp"
|
protocol = "tcp"
|
||||||
dialOptions = append(dialOptions, libdial.WithAfterHook(libdial.AfterHook{Hook: frpNet.DialHookWebsocket()}))
|
|
||||||
}
|
}
|
||||||
if ctl.clientCfg.ConnectServerLocalIP != "" {
|
if ctl.clientCfg.ConnectServerLocalIP != "" {
|
||||||
dialOptions = append(dialOptions, libdial.WithLocalAddr(ctl.clientCfg.ConnectServerLocalIP))
|
dialOptions = append(dialOptions, libdial.WithLocalAddr(ctl.clientCfg.ConnectServerLocalIP))
|
||||||
@ -255,11 +268,18 @@ func (ctl *Control) connectServer() (conn net.Conn, err error) {
|
|||||||
libdial.WithKeepAlive(time.Duration(ctl.clientCfg.DialServerKeepAlive)*time.Second),
|
libdial.WithKeepAlive(time.Duration(ctl.clientCfg.DialServerKeepAlive)*time.Second),
|
||||||
libdial.WithProxy(proxyType, addr),
|
libdial.WithProxy(proxyType, addr),
|
||||||
libdial.WithProxyAuth(auth),
|
libdial.WithProxyAuth(auth),
|
||||||
libdial.WithTLSConfig(tlsConfig),
|
libdial.WithTLSConfig(tlsConfig), // TLS AfterHook has math.MaxUint64 priority
|
||||||
libdial.WithAfterHook(libdial.AfterHook{
|
libdial.WithAfterHook(libdial.AfterHook{
|
||||||
Hook: frpNet.DialHookCustomTLSHeadByte(tlsConfig != nil, ctl.clientCfg.DisableCustomTLSFirstByte),
|
Priority: 1, // should be executed before TLS AfterHook but after the rest of the AfterHooks (except for wss)
|
||||||
|
Hook: frpNet.DialHookCustomTLSHeadByte(tlsConfig != nil, ctl.clientCfg.DisableCustomTLSFirstByte),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
if websocketAfterHook != nil {
|
||||||
|
// websocketAfterHook must be appended after TLS AfterHook because they both might have the
|
||||||
|
// same priority of math.MaxUint64 in case of wss but TLS AfterHook must be executed first
|
||||||
|
dialOptions = append(dialOptions, libdial.WithAfterHook(*websocketAfterHook))
|
||||||
|
}
|
||||||
|
|
||||||
conn, err = libdial.Dial(
|
conn, err = libdial.Dial(
|
||||||
net.JoinHostPort(ctl.clientCfg.ServerAddr, strconv.Itoa(ctl.clientCfg.ServerPort)),
|
net.JoinHostPort(ctl.clientCfg.ServerAddr, strconv.Itoa(ctl.clientCfg.ServerPort)),
|
||||||
dialOptions...,
|
dialOptions...,
|
||||||
|
@ -19,6 +19,7 @@ import (
|
|||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"math"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net"
|
"net"
|
||||||
"runtime"
|
"runtime"
|
||||||
@ -256,9 +257,21 @@ func (svr *Service) login() (conn net.Conn, session *fmux.Session, err error) {
|
|||||||
}
|
}
|
||||||
dialOptions := []libdial.DialOption{}
|
dialOptions := []libdial.DialOption{}
|
||||||
protocol := svr.cfg.Protocol
|
protocol := svr.cfg.Protocol
|
||||||
if protocol == "websocket" {
|
var websocketAfterHook *libdial.AfterHook
|
||||||
|
if protocol == "websocket" || protocol == "wss" {
|
||||||
|
if protocol == "wss" {
|
||||||
|
websocketAfterHook = &libdial.AfterHook{
|
||||||
|
Priority: math.MaxUint64, // in case of wss, we first want to make the TLS handshake and then switch protocols from https to wss
|
||||||
|
Hook: frpNet.DialHookWebsocket(true),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
websocketAfterHook = &libdial.AfterHook{
|
||||||
|
Priority: 0, // in case of ws, we first want to switch protocols from http to ws, and only then make the TLS handshake in case TLS is enabled
|
||||||
|
Hook: frpNet.DialHookWebsocket(false),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protocol = "tcp"
|
protocol = "tcp"
|
||||||
dialOptions = append(dialOptions, libdial.WithAfterHook(libdial.AfterHook{Hook: frpNet.DialHookWebsocket()}))
|
|
||||||
}
|
}
|
||||||
if svr.cfg.ConnectServerLocalIP != "" {
|
if svr.cfg.ConnectServerLocalIP != "" {
|
||||||
dialOptions = append(dialOptions, libdial.WithLocalAddr(svr.cfg.ConnectServerLocalIP))
|
dialOptions = append(dialOptions, libdial.WithLocalAddr(svr.cfg.ConnectServerLocalIP))
|
||||||
@ -269,11 +282,18 @@ func (svr *Service) login() (conn net.Conn, session *fmux.Session, err error) {
|
|||||||
libdial.WithKeepAlive(time.Duration(svr.cfg.DialServerKeepAlive)*time.Second),
|
libdial.WithKeepAlive(time.Duration(svr.cfg.DialServerKeepAlive)*time.Second),
|
||||||
libdial.WithProxy(proxyType, addr),
|
libdial.WithProxy(proxyType, addr),
|
||||||
libdial.WithProxyAuth(auth),
|
libdial.WithProxyAuth(auth),
|
||||||
libdial.WithTLSConfig(tlsConfig),
|
libdial.WithTLSConfig(tlsConfig), // TLS AfterHook has math.MaxUint64 priority
|
||||||
libdial.WithAfterHook(libdial.AfterHook{
|
libdial.WithAfterHook(libdial.AfterHook{
|
||||||
Hook: frpNet.DialHookCustomTLSHeadByte(tlsConfig != nil, svr.cfg.DisableCustomTLSFirstByte),
|
Priority: 1, // should be executed before TLS AfterHook but after the rest of the AfterHooks (except for wss)
|
||||||
|
Hook: frpNet.DialHookCustomTLSHeadByte(tlsConfig != nil, svr.cfg.DisableCustomTLSFirstByte),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
if websocketAfterHook != nil {
|
||||||
|
// websocketAfterHook must be appended after TLS AfterHook because they both might have the
|
||||||
|
// same priority of math.MaxUint64 in case of wss but TLS AfterHook must be executed first
|
||||||
|
dialOptions = append(dialOptions, libdial.WithAfterHook(*websocketAfterHook))
|
||||||
|
}
|
||||||
|
|
||||||
conn, err = libdial.Dial(
|
conn, err = libdial.Dial(
|
||||||
net.JoinHostPort(svr.cfg.ServerAddr, strconv.Itoa(svr.cfg.ServerPort)),
|
net.JoinHostPort(svr.cfg.ServerAddr, strconv.Itoa(svr.cfg.ServerPort)),
|
||||||
dialOptions...,
|
dialOptions...,
|
||||||
|
@ -85,7 +85,7 @@ func init() {
|
|||||||
func RegisterCommonFlags(cmd *cobra.Command) {
|
func RegisterCommonFlags(cmd *cobra.Command) {
|
||||||
cmd.PersistentFlags().StringVarP(&serverAddr, "server_addr", "s", "127.0.0.1:7000", "frp server's address")
|
cmd.PersistentFlags().StringVarP(&serverAddr, "server_addr", "s", "127.0.0.1:7000", "frp server's address")
|
||||||
cmd.PersistentFlags().StringVarP(&user, "user", "u", "", "user")
|
cmd.PersistentFlags().StringVarP(&user, "user", "u", "", "user")
|
||||||
cmd.PersistentFlags().StringVarP(&protocol, "protocol", "p", "tcp", "tcp or kcp or websocket")
|
cmd.PersistentFlags().StringVarP(&protocol, "protocol", "p", "tcp", "tcp or kcp or websocket or wss")
|
||||||
cmd.PersistentFlags().StringVarP(&token, "token", "t", "", "auth token")
|
cmd.PersistentFlags().StringVarP(&token, "token", "t", "", "auth token")
|
||||||
cmd.PersistentFlags().StringVarP(&logLevel, "log_level", "", "info", "log level")
|
cmd.PersistentFlags().StringVarP(&logLevel, "log_level", "", "info", "log level")
|
||||||
cmd.PersistentFlags().StringVarP(&logFile, "log_file", "", "console", "console or file path")
|
cmd.PersistentFlags().StringVarP(&logFile, "log_file", "", "console", "console or file path")
|
||||||
|
@ -87,7 +87,7 @@ user = your_name
|
|||||||
login_fail_exit = true
|
login_fail_exit = true
|
||||||
|
|
||||||
# communication protocol used to connect to server
|
# communication protocol used to connect to server
|
||||||
# now it supports tcp, kcp and websocket, default is tcp
|
# now it supports tcp, kcp, websocket and wss, default is tcp
|
||||||
protocol = tcp
|
protocol = tcp
|
||||||
|
|
||||||
# set client binding ip when connect server, default is empty.
|
# set client binding ip when connect server, default is empty.
|
||||||
|
@ -9,4 +9,4 @@ FROM alpine:3
|
|||||||
|
|
||||||
COPY --from=building /building/bin/frpc /usr/bin/frpc
|
COPY --from=building /building/bin/frpc /usr/bin/frpc
|
||||||
|
|
||||||
ENTRYPOINT ["/usr/bin/frpc"]
|
ENTRYPOINT /usr/bin/frpc -c /etc/frp/frpc.ini
|
||||||
|
@ -9,4 +9,4 @@ FROM alpine:3
|
|||||||
|
|
||||||
COPY --from=building /building/bin/frps /usr/bin/frps
|
COPY --from=building /building/bin/frps /usr/bin/frps
|
||||||
|
|
||||||
ENTRYPOINT ["/usr/bin/frps"]
|
ENTRYPOINT /usr/bin/frps -c /etc/frp/frps.ini
|
||||||
|
@ -215,6 +215,10 @@ func (cfg *ClientCommonConf) Validate() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if cfg.TLSEnable == false {
|
if cfg.TLSEnable == false {
|
||||||
|
if cfg.Protocol == "wss" {
|
||||||
|
return fmt.Errorf("tls_enable must be true for wss support")
|
||||||
|
}
|
||||||
|
|
||||||
if cfg.TLSCertFile != "" {
|
if cfg.TLSCertFile != "" {
|
||||||
fmt.Println("WARNING! tls_cert_file is invalid when tls_enable is false")
|
fmt.Println("WARNING! tls_cert_file is invalid when tls_enable is false")
|
||||||
}
|
}
|
||||||
@ -228,7 +232,7 @@ func (cfg *ClientCommonConf) Validate() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg.Protocol != "tcp" && cfg.Protocol != "kcp" && cfg.Protocol != "websocket" {
|
if cfg.Protocol != "tcp" && cfg.Protocol != "kcp" && cfg.Protocol != "websocket" && cfg.Protocol != "wss" {
|
||||||
return fmt.Errorf("invalid protocol")
|
return fmt.Errorf("invalid protocol")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,15 +21,21 @@ func DialHookCustomTLSHeadByte(enableTLS bool, disableCustomTLSHeadByte bool) li
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func DialHookWebsocket() libdial.AfterHookFunc {
|
func DialHookWebsocket(isSecure bool) libdial.AfterHookFunc {
|
||||||
return func(ctx context.Context, c net.Conn, addr string) (context.Context, net.Conn, error) {
|
return func(ctx context.Context, c net.Conn, addr string) (context.Context, net.Conn, error) {
|
||||||
addr = "ws://" + addr + FrpWebsocketPath
|
addrScheme := "ws"
|
||||||
|
originScheme := "http"
|
||||||
|
if isSecure {
|
||||||
|
addrScheme = "wss"
|
||||||
|
originScheme = "https"
|
||||||
|
}
|
||||||
|
addr = addrScheme + "://" + addr + FrpWebsocketPath
|
||||||
uri, err := url.Parse(addr)
|
uri, err := url.Parse(addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
origin := "http://" + uri.Host
|
origin := originScheme + "://" + uri.Host
|
||||||
cfg, err := websocket.NewConfig(addr, origin)
|
cfg, err := websocket.NewConfig(addr, origin)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
|
Loading…
Reference in New Issue
Block a user