AI 摘要(由 ChatGPT 总结生成):
本文介绍了对FRP(Fast Reverse Proxy)的改造计划,包括远程加载配置文件、配置文件自动删除、修改客户端使用Proxy的流量特征、TLS默认字节修改以及命令方式开启socks5代理等。改进使FRP更适用于红队代理场景,提高安全性和灵活性。详细改造步骤包括对源码的多处修改,如在`cmd/frpc/sub/root.go`中添加参数以实现配置文件自动删除,在`pkg/config/value.go`中实现远程加载配置文件功能,在`server/proxy/proxy.go`中修改客户端使用Proxy的流量特征,以及在`pkg/util/net/tls.go`中修改TLS默认字节。最后,通过命令方式开启socks5代理以避免配置文件加载请求。

前言

该 IDEA 源于一次外网打入内网后做代理时的灵感,原版 FRP 只能本地加载配置文件,故联想到可不可以“魔改” FRP 使其远程加载配置文件以及实现其它操作,遂事后去搜索借鉴其它大佬的思路以及教程,对 FRP 进行改造,使其更加契合红队做代理时的场景。

本文是基于最新版 FRP 0.48.0 版本的改造。话不多说,下面教程开始!

改造教程

基于项目源码修改,最好拥有简单的代码能力。

配置文件自动删除

原版 FRPC 只能基于本地文件加载运行,若后续不手动删除配置文件,则配置文件会遗留在目标机器上,后续可能被别人拿来分析并获取你的公网 IP 等,更甚者直接溯源到你本人,故运行 FRPC 时顺手删除配置文件是必要的。

功能点在 cmd/frpc/sub/root.go 文件中修改。原理是在 init 中注册参数,然后判断参数是否开启,开启就删除。代码如下:

package sub

import (
    ……
)

const (
    ……
)

var (
    cfgFile     string
    ……
    bindPort           int

    tlsEnable bool
    
    // 添加该行
    delEnable bool
    // END
)

func init() {
    rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "./frpc.ini", "config file of frpc")
    rootCmd.PersistentFlags().StringVarP(&cfgDir, "config_dir", "", "", "config directory, run one frpc service for each file in config directory")
    rootCmd.PersistentFlags().BoolVarP(&showVersion, "version", "v", false, "version of frpc")

    // 添加该行
    rootCmd.PersistentFlags().BoolVarP(&delEnable, "delini", "d", false, "enable auto delete frpc.ini (only local files)")
    // END
}

func RegisterCommonFlags(cmd *cobra.Command) {
    ……
}

var rootCmd = &cobra.Command{
    ……
}

func Execute() {
    ……
}

func handleSignal(svr *client.Service, doneCh chan struct{}) {
    ……
}

func parseClientCommonCfgFromCmd() (cfg config.ClientCommonConf, err error) {
    ……
}

func runClient(cfgFilePath string) error {
    ……
}

func startService(
    ……
) (err error) {
    log.InitLog(cfg.LogWay, cfg.LogFile, cfg.LogLevel,
    ……
    svr, errRet := client.NewService(cfg, pxyCfgs, visitorCfgs, cfgFile)
    if errRet != nil {
        err = errRet
        return
    }

    // 添加该行
    if delEnable == true {
        err := os.Remove(cfgFile)
        if err != nil {
            return err
        }
    }
    // END

    closedDoneCh := make(chan struct{})
    ……
    return
}

使用方法:指定本地配置文件时多带一个 -d--delini 参数就行,如下图:

image-20230426193927745

远程加载配置文件

使得配置文件可以从网络加载,此处可以将配置文件直接写入到 FRPC 源码中,但这样不利于后期修改,故舍弃该方式,加入从网络加载方式。

功能点在 pkg/config/value.go 文件中修改。指定配置文件的参数若是 http 请求,则对其进行请求加载,否则,从对应指定路径加载。此处只需将 GetRenderedConfFromFile 函数功能修改即可,修改为如下:

func GetRenderedConfFromFile(path string) (out []byte, err error) {
    var b []byte
    rawUrl := path
    if strings.Contains(rawUrl, "http") {
        log.Info("Remote load ini file")
        response, _err1 := http.Get(path)
        if _err1 != nil {
            return
        }
        defer response.Body.Close()
        body, _err := io.ReadAll(response.Body)
        if _err != nil {
            return
        }
        httpContent := string(body)
        var content = []byte(httpContent)
        out, err = RenderContent(content)
        return

    } else {
        log.Info("Local load ini file")
        b, err = os.ReadFile(path)
        if err != nil {
            return
        }
        localContent := string(b)
        var content = []byte(localContent)
        out, err = RenderContent(content)
        return
    }
}

功能演示如下图:

image-20230426195139444

修改客户端使用Proxy的流量特征

正常情况下建议 FRP 服务端开启 tls_only = true 选项,同时 FRP 客户端配置文件中指定 tls_enable = true 选项以加密传输的流量,这样可以避免暴露你的服务器 IP 或本地 IP ,如果不想开启 TLS 选项的话,又不想暴露相关 IP ,那么可以对其进行如下修改以隐藏流量特征。

功能点在 server/proxy/proxy.go 文件中修改,将 GetWorkConnFromPool 函数内代码手动指定 IP 地址(IP 可随意修改),代码如下:

        ……
        if src != nil {
            srcAddr, srcPortStr, _ = net.SplitHostPort(src.String())
            // 追加如下
            srcAddr = "127.0.0.1"
            srcPort, _ = strconv.Atoi(srcPortStr)
        }
        if dst != nil {
            dstAddr, dstPortStr, _ = net.SplitHostPort(dst.String())
            // 追加如下
            dstAddr = "127.0.0.1"
            dstPort, _ = strconv.Atoi(dstPortStr)
        }
        ……

上述问题建议在配置文件中启用 tls_enable 参数以规避。

TLS默认字节修改

从 v0.25.0 版本开始 FRPC 和 FRPS 之间支持通过 TLS 协议加密传输,为了端口复用,FRP 建立 TLS 连接的第一个字节为 0x17 ,有些流量识别程序识别到特定流量,可能会阻拦,故我们可以对其进行修改。

功能点在 pkg/util/net/tls.go 文件中修改,如下:

……
// var FRPTLSHeadByte = 0x17
// 修改为下方,可自定义其它
var FRPTLSHeadByte = 0x88

func CheckAndEnableTLSServerConnWithTimeout(
    c net.Conn, tlsConfig *tls.Config, tlsOnly bool, timeout time.Duration,
) (out net.Conn, isTLS bool, custom bool, err error) {
    sc, r := gnet.NewSharedConnSize(c, 2)
    buf := make([]byte, 1)
    var n int
    _ = c.SetReadDeadline(time.Now().Add(timeout))
    n, err = r.Read(buf)
    _ = c.SetReadDeadline(time.Time{})
    if err != nil {
        return
    }
……

该方式在新版本中可在客户端配置中加入 disable_custom_tls_first_byte = true 参数使得 TLS 不发送 0x17

命令方式开启socks5代理

下述方法使用命令方式开启 socks5 代理,以避免配置文件加载请求。

修改源码文件 cmd/frpc/sub/tcp.go 并添加相关参数,如下:

package sub

import (
    ……
)

func init() {
    ……

    //添加这几行
    tcpCmd.PersistentFlags().StringVarP(&pluginName, "plugin", "", "", "plugins")
    tcpCmd.PersistentFlags().StringVarP(&pluginUser, "plugin_user", "", "", "plugins user name")
    tcpCmd.PersistentFlags().StringVarP(&pluginPass, "plugin_pass", "", "", "plguins user password")
    //END

    rootCmd.AddCommand(tcpCmd)
}

var tcpCmd = &cobra.Command{
        ……
        cfg.UseEncryption = useEncryption
        cfg.UseCompression = useCompression

        //添加这几行
        cfg.Plugin = pluginName
        if cfg.Plugin != "" {
            cfg.PluginParams = make(map[string]string)
            cfg.PluginParams["plugin_user"] = pluginUser
            cfg.PluginParams["plugin_passwd"] = pluginPass
        }
        //END
        ……
}

再修改 cmd/frpc/sub/root.go 文件,增加如下参数:

var (
    cfgFile    string
    ……
    bindPort    int

    tlsEnable bool

    //添加这几行
    pluginName string
    pluginUser string
    pluginPass string
    //END
)

最后使用方式如下:

./frpc tcp -s [IP]:[PORT] -r [远端端口] -t [Token] --plugin socks5 --plugin_user [鉴权用户] --plugin_pass [鉴权密码] -n [代理名称]

如图所示:

image-20230426215154974

此方法建议在 Windows 下使用,Linux 使用可以看到完整命令参数。

参考

End

本文标题:FRP改造计划

本文链接:https://www.isisy.com/1458.html

除非另有说明,本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议

声明:转载请注明文章来源。

如果觉得我的文章对你有用,请随意赞赏