在自己的Go程序中集成Frp客户端

本文介绍根据工作中需在go语言开发的客户端程序集成frp客户端,实现内网穿透的实践案列及核心代码示例。

应用场景:如数据同步工具等客户端,需将内网服务映射的服务器,集成到程序中更加灵活而无需单独去维护一个frpc进程。

因为frp是基于Go语言的开源项目,参考源代码可见frpc启动核心代码,直接提取到项目中即可。

核心代码如下:

package main

import (
	"context"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/fatedier/frp/client"
	v1 "github.com/fatedier/frp/pkg/config/v1"
	"github.com/fatedier/frp/pkg/util/log"
)

func main() {

	cfg := &v1.ClientCommonConfig{
		ServerAddr: "139.9.150.125",
		ServerPort: 8222,
		User:       "admin",
		Auth: v1.AuthClientConfig{
			Token: "jxkj123",
		},
	}

	proxyCfgs := []v1.ProxyConfigurer{
		&v1.TCPProxyConfig{
			ProxyBaseConfig: v1.ProxyBaseConfig{
				Name: "test",
				Type: "tcp",
				ProxyBackend: v1.ProxyBackend{
					LocalIP:   "127.0.0.1",
					LocalPort: 5080,
				},
			},
			RemotePort: 8787,
		},
	}

	visitorCfgs := []v1.VisitorConfigurer{}

	err := startService(cfg, proxyCfgs, visitorCfgs, "")
	if err != nil {
		return
	}
}

func startService(
	cfg *v1.ClientCommonConfig,
	proxyCfgs []v1.ProxyConfigurer,
	visitorCfgs []v1.VisitorConfigurer,
	cfgFile string,
) error {
	log.InitLogger(cfg.Log.To, cfg.Log.Level, int(cfg.Log.MaxDays), cfg.Log.DisablePrintColor)

	if cfgFile != "" {
		log.Infof("start frpc service for config file [%s]", cfgFile)
		defer log.Infof("frpc service for config file [%s] stopped", cfgFile)
	}
	svr, err := client.NewService(client.ServiceOptions{
		Common:         cfg,
		ProxyCfgs:      proxyCfgs,
		VisitorCfgs:    visitorCfgs,
		ConfigFilePath: cfgFile,
	})
	if err != nil {
		return err
	}

	shouldGracefulClose := cfg.Transport.Protocol == "kcp" || cfg.Transport.Protocol == "quic"
	// Capture the exit signal if we use kcp or quic.
	if shouldGracefulClose {
		go handleTermSignal(svr)
	}
	return svr.Run(context.Background())
}

func handleTermSignal(svr *client.Service) {
	ch := make(chan os.Signal, 1)
	signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
	<-ch
	svr.GracefulClose(500 * time.Millisecond)
}

参考如上main方法的配置即可简单实现客户端的运行。