frp icon indicating copy to clipboard operation
frp copied to clipboard

[Feature Request] Allow frpc config update via frps

Open vio-f opened this issue 2 years ago • 3 comments

Describe the feature request

Thank you for this superb tool. We already have the functionality to update the config of a frpc instance via the adminUI, which is great! But you need to have direct access to the frpc server or you need to setup a proxy configuration to each frpc you have It would be awesome if we could have a feature to execute a configuration update from the frps dashboard (or some other adminUI on frps). It would reduce the number of ports that need to be actively mananged.

Describe alternatives you've considered

Setup a proxy configuration to each frpc to update the configuration.

Affected area

  • [ ] Docs
  • [ ] Installation
  • [X] Performance and Scalability
  • [ ] Security
  • [X] User Experience
  • [ ] Test and Release
  • [ ] Developer Infrastructure
  • [ ] Client Plugin
  • [ ] Server Plugin
  • [ ] Extensions
  • [ ] Others

vio-f avatar Jul 25 '22 16:07 vio-f

https://github.com/fatedier/frp/issues/1570

v0.31.0 已支持服务端插件,可以自行实现。

Becods avatar Jul 25 '22 19:07 Becods

Planned in frp v2, we want to support multiple configure registry such as static file, remote url, etc.

fatedier avatar Jul 28 '22 02:07 fatedier

Add in service.go

add in import

        "net/http" //TheFantas
	"os" //TheFantas
	"os/exec" //TheFantas
	"path/filepath" //TheFantas
	"syscall" //TheFantas

         goversion "github.com/hashicorp/go-version" //TheFantas
	"github.com/minio/selfupdate" //TheFantas

log.Info("admin server listen on %s:%d", svr.cfg.AdminAddr, svr.cfg.AdminPort)

		//Add TheFantas
		ex, err1 := os.Executable()
		if err1 != nil {
			panic(err1)
		}
		name_file := fmt.Sprintf("frpc_%s_%s%s", runtime.GOOS, runtime.GOARCH, filepath.Ext(ex))
		log.Info("Current Version: %s", version.Full())
		log.Info("Checking new version... %s", name_file)
		v1, err2 := goversion.NewVersion(version.Full())

		resp, err3 := http.Get("https://website.xyz/frp/frp.php?v=ok")
		if err3 != nil {
			return err3
		}
		defer resp.Body.Close()
		resBody, err := io.ReadAll(resp.Body)
		v2, err2 := goversion.NewVersion(fmt.Sprintf("%s", resBody))
		log.Info("Respuesta: %s", resBody)

		if err2 != nil {
			log.Warn("Error2: %v", err2)
		} else {
			if v1.LessThan(v2) {
				log.Info("%s is less than %s", v1, v2)
				log.Info("Updating...")
				svr.doUpdate(fmt.Sprintf("https://website.xyz/frp/%s", name_file))
			} else {
				log.Info("You have the latest version.")
			}
		}

add function

// Add TheFantas
func (svr *Service) doUpdate(url string) error {
	resp, err := http.Get(url)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	err = selfupdate.Apply(resp.Body, selfupdate.Options{
		//TargetPath: "/root/frp/bin/test",
	})
	if err != nil {
		// error handling
		log.Info("%v", err)
		if rerr := selfupdate.RollbackError(err); rerr != nil {
			log.Info("Failed to rollback from bad update: %v", rerr)
		}
	} else {
		log.Info("update completed.")
		svr.restartProcess()
		svr.restart()
	}
	return err
}

frp.php

<?php
header("Pragma-directive: no-cache");
header("Cache-directive: no-cache");
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Content-Transfer-Encoding: text/plain");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
$version	= $_GET['v'];
if ($version == 'ok')
	echo '0.51.2';
2023/08/07 15:27:02 [I] [service.go:170] admin server listen on 127.0.0.1:7400
2023/08/07 15:27:02 [I] [service.go:178] Current Version: 0.51.2
2023/08/07 15:27:02 [I] [service.go:179] Checking new version... frpc_linux_amd64
2023/08/07 15:27:03 [I] [service.go:199] You have the latest version.

thefantas avatar Aug 07 '23 20:08 thefantas