forked from Mxmilu666/frp
Compare commits
6 Commits
dev
...
a0ae9879c0
| Author | SHA1 | Date | |
|---|---|---|---|
| a0ae9879c0 | |||
|
9072177b79
|
|||
| e4f1ec648f | |||
|
a76ecfe76c
|
|||
|
58126df910
|
|||
|
bc1e44268a
|
50
.gitea/workflows/build-all.yaml
Normal file
50
.gitea/workflows/build-all.yaml
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
# 由于成本问题,现已全面转向 Github Actions 构建
|
||||||
|
name: Build FRP Binaries
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- '**'
|
||||||
|
tags:
|
||||||
|
- '**'
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
tag:
|
||||||
|
description: 'Manual build tag'
|
||||||
|
required: false
|
||||||
|
default: 'manual'
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Build and Package FRP
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout source
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: '1.22'
|
||||||
|
|
||||||
|
- name: Set up dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get update -y
|
||||||
|
sudo apt-get install -y zip make gcc g++ upx
|
||||||
|
|
||||||
|
- name: Run build script
|
||||||
|
run: |
|
||||||
|
chmod +x ./package.sh
|
||||||
|
./package.sh
|
||||||
|
|
||||||
|
- name: Upload build artifacts
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: frp-packages
|
||||||
|
path: release/packages
|
||||||
4
.github/FUNDING.yml
vendored
4
.github/FUNDING.yml
vendored
@@ -1,4 +0,0 @@
|
|||||||
# These are supported funding model platforms
|
|
||||||
|
|
||||||
github: [fatedier]
|
|
||||||
custom: ["https://afdian.com/a/fatedier"]
|
|
||||||
3
.github/pull_request_template.md
vendored
3
.github/pull_request_template.md
vendored
@@ -1,3 +0,0 @@
|
|||||||
### WHY
|
|
||||||
|
|
||||||
<!-- author to complete -->
|
|
||||||
93
.github/workflows/build-all.yaml
vendored
Normal file
93
.github/workflows/build-all.yaml
vendored
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
name: Build FRP Binaries
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- '**'
|
||||||
|
tags:
|
||||||
|
- '**'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Build FRP ${{ matrix.goos }}-${{ matrix.goarch }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
goos: [linux, windows, darwin, freebsd, openbsd, android]
|
||||||
|
goarch: [amd64, arm, arm64]
|
||||||
|
exclude:
|
||||||
|
- goos: darwin
|
||||||
|
goarch: arm
|
||||||
|
- goos: freebsd
|
||||||
|
goarch: arm
|
||||||
|
- goos: openbsd
|
||||||
|
goarch: arm
|
||||||
|
- goos: android
|
||||||
|
goarch: amd64
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout source
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: '1.22'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get update -y
|
||||||
|
sudo apt-get install -y zip tar make gcc g++ upx
|
||||||
|
|
||||||
|
- name: Build FRP for ${{ matrix.goos }}-${{ matrix.goarch }}
|
||||||
|
run: |
|
||||||
|
mkdir -p release/packages
|
||||||
|
|
||||||
|
echo "Building for ${{ matrix.goos }}-${{ matrix.goarch }}"
|
||||||
|
|
||||||
|
# 构建版本号
|
||||||
|
make
|
||||||
|
version=$(./bin/frps --version)
|
||||||
|
echo "Detected version: $version"
|
||||||
|
|
||||||
|
export GOOS=${{ matrix.goos }}
|
||||||
|
export GOARCH=${{ matrix.goarch }}
|
||||||
|
export CGO_ENABLED=0
|
||||||
|
|
||||||
|
# 构建可执行文件
|
||||||
|
make frpc frps
|
||||||
|
|
||||||
|
if [ "${{ matrix.goos }}" = "windows" ]; then
|
||||||
|
if [ -f "./bin/frpc" ]; then mv ./bin/frpc ./bin/frpc.exe; fi
|
||||||
|
if [ -f "./bin/frps" ]; then mv ./bin/frps ./bin/frps.exe; fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
out_dir="release/packages/frp_${version}_${{ matrix.goos }}_${{ matrix.goarch }}"
|
||||||
|
mkdir -p "$out_dir"
|
||||||
|
|
||||||
|
if [ "${{ matrix.goos }}" = "windows" ]; then
|
||||||
|
mv ./bin/frpc.exe "$out_dir/frpc.exe"
|
||||||
|
mv ./bin/frps.exe "$out_dir/frps.exe"
|
||||||
|
else
|
||||||
|
mv ./bin/frpc "$out_dir/frpc"
|
||||||
|
mv ./bin/frps "$out_dir/frps"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cp LICENSE "$out_dir"
|
||||||
|
cp -f conf/frpc.toml "$out_dir"
|
||||||
|
cp -f conf/frps.toml "$out_dir"
|
||||||
|
|
||||||
|
- name: Upload artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: LoliaFrp_${{ matrix.goos }}_${{ matrix.goarch }}
|
||||||
|
path: |
|
||||||
|
release/packages/frp_*
|
||||||
|
retention-days: 7
|
||||||
@@ -206,8 +206,9 @@ func (m *serverMetrics) GetProxiesByType(proxyType string) []*ProxyStats {
|
|||||||
m.mu.Lock()
|
m.mu.Lock()
|
||||||
defer m.mu.Unlock()
|
defer m.mu.Unlock()
|
||||||
|
|
||||||
|
filterAll := proxyType == "" || proxyType == "all"
|
||||||
for name, proxyStats := range m.info.ProxyStatistics {
|
for name, proxyStats := range m.info.ProxyStatistics {
|
||||||
if proxyStats.ProxyType != proxyType {
|
if !filterAll && proxyStats.ProxyType != proxyType {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,8 +234,9 @@ func (m *serverMetrics) GetProxiesByTypeAndName(proxyType string, proxyName stri
|
|||||||
m.mu.Lock()
|
m.mu.Lock()
|
||||||
defer m.mu.Unlock()
|
defer m.mu.Unlock()
|
||||||
|
|
||||||
|
filterAll := proxyType == "" || proxyType == "all"
|
||||||
for name, proxyStats := range m.info.ProxyStatistics {
|
for name, proxyStats := range m.info.ProxyStatistics {
|
||||||
if proxyStats.ProxyType != proxyType {
|
if !filterAll && proxyStats.ProxyType != proxyType {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
package version
|
package version
|
||||||
|
|
||||||
var version = "0.65.0"
|
var version = "LoliaFRP-0.65.0"
|
||||||
|
|
||||||
func Full() string {
|
func Full() string {
|
||||||
return version
|
return version
|
||||||
|
|||||||
@@ -94,6 +94,28 @@ func (cm *ControlManager) Close() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// KickByProxyName finds the Control that manages the given proxy (tunnel) name and closes
|
||||||
|
// the entire control connection (disconnects the frpc). Returns an error if no such proxy is found.
|
||||||
|
func (cm *ControlManager) KickByProxyName(proxyName string) error {
|
||||||
|
cm.mu.RLock()
|
||||||
|
var target *Control
|
||||||
|
for _, ctl := range cm.ctlsByRunID {
|
||||||
|
ctl.mu.RLock()
|
||||||
|
_, ok := ctl.proxies[proxyName]
|
||||||
|
ctl.mu.RUnlock()
|
||||||
|
if ok {
|
||||||
|
target = ctl
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cm.mu.RUnlock()
|
||||||
|
|
||||||
|
if target == nil {
|
||||||
|
return fmt.Errorf("no proxy found with name [%s]", proxyName)
|
||||||
|
}
|
||||||
|
return target.Close()
|
||||||
|
}
|
||||||
|
|
||||||
type Control struct {
|
type Control struct {
|
||||||
// all resource managers and controllers
|
// all resource managers and controllers
|
||||||
rc *controller.ResourceController
|
rc *controller.ResourceController
|
||||||
|
|||||||
@@ -52,8 +52,10 @@ func (svr *Service) registerRouteHandlers(helper *httppkg.RouterRegisterHelper)
|
|||||||
subRouter.HandleFunc("/api/serverinfo", svr.apiServerInfo).Methods("GET")
|
subRouter.HandleFunc("/api/serverinfo", svr.apiServerInfo).Methods("GET")
|
||||||
subRouter.HandleFunc("/api/proxy/{type}", svr.apiProxyByType).Methods("GET")
|
subRouter.HandleFunc("/api/proxy/{type}", svr.apiProxyByType).Methods("GET")
|
||||||
subRouter.HandleFunc("/api/proxy/{type}/{name}", svr.apiProxyByTypeAndName).Methods("GET")
|
subRouter.HandleFunc("/api/proxy/{type}/{name}", svr.apiProxyByTypeAndName).Methods("GET")
|
||||||
|
subRouter.HandleFunc("/api/proxy/{name}/kick", svr.apiKickProxyByName).Methods("POST")
|
||||||
subRouter.HandleFunc("/api/traffic/{name}", svr.apiProxyTraffic).Methods("GET")
|
subRouter.HandleFunc("/api/traffic/{name}", svr.apiProxyTraffic).Methods("GET")
|
||||||
subRouter.HandleFunc("/api/proxies", svr.deleteProxies).Methods("DELETE")
|
subRouter.HandleFunc("/api/proxies", svr.deleteProxies).Methods("DELETE")
|
||||||
|
subRouter.HandleFunc("/api/proxies", svr.apiProxiesAll).Methods("GET")
|
||||||
|
|
||||||
// view
|
// view
|
||||||
subRouter.Handle("/favicon.ico", http.FileServer(helper.AssetsFS)).Methods("GET")
|
subRouter.Handle("/favicon.ico", http.FileServer(helper.AssetsFS)).Methods("GET")
|
||||||
@@ -211,6 +213,29 @@ type GetProxyInfoResp struct {
|
|||||||
Proxies []*ProxyStatsInfo `json:"proxies"`
|
Proxies []*ProxyStatsInfo `json:"proxies"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GET /api/proxies
|
||||||
|
// Return all proxies across types (tcp, udp, http, https, stcp, xtcp, tcpmux)
|
||||||
|
func (svr *Service) apiProxiesAll(w http.ResponseWriter, r *http.Request) {
|
||||||
|
res := GeneralResponse{Code: 200}
|
||||||
|
defer func() {
|
||||||
|
log.Infof("http response [%s]: code [%d]", r.URL.Path, res.Code)
|
||||||
|
w.WriteHeader(res.Code)
|
||||||
|
if len(res.Msg) > 0 {
|
||||||
|
_, _ = w.Write([]byte(res.Msg))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
log.Infof("http request: [%s]", r.URL.Path)
|
||||||
|
|
||||||
|
proxyInfoResp := GetProxyInfoResp{}
|
||||||
|
proxyInfoResp.Proxies = svr.getProxyStatsByType("all")
|
||||||
|
slices.SortFunc(proxyInfoResp.Proxies, func(a, b *ProxyStatsInfo) int {
|
||||||
|
return cmp.Compare(a.Name, b.Name)
|
||||||
|
})
|
||||||
|
|
||||||
|
buf, _ := json.Marshal(&proxyInfoResp)
|
||||||
|
res.Msg = string(buf)
|
||||||
|
}
|
||||||
|
|
||||||
// /api/proxy/:type
|
// /api/proxy/:type
|
||||||
func (svr *Service) apiProxyByType(w http.ResponseWriter, r *http.Request) {
|
func (svr *Service) apiProxyByType(w http.ResponseWriter, r *http.Request) {
|
||||||
res := GeneralResponse{Code: 200}
|
res := GeneralResponse{Code: 200}
|
||||||
@@ -237,6 +262,7 @@ func (svr *Service) apiProxyByType(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (svr *Service) getProxyStatsByType(proxyType string) (proxyInfos []*ProxyStatsInfo) {
|
func (svr *Service) getProxyStatsByType(proxyType string) (proxyInfos []*ProxyStatsInfo) {
|
||||||
|
// mem.StatsCollector now supports proxyType=="all" or "" to return all proxies
|
||||||
proxyStats := mem.StatsCollector.GetProxiesByType(proxyType)
|
proxyStats := mem.StatsCollector.GetProxiesByType(proxyType)
|
||||||
proxyInfos = make([]*ProxyStatsInfo, 0, len(proxyStats))
|
proxyInfos = make([]*ProxyStatsInfo, 0, len(proxyStats))
|
||||||
for _, ps := range proxyStats {
|
for _, ps := range proxyStats {
|
||||||
@@ -308,6 +334,37 @@ func (svr *Service) apiProxyByTypeAndName(w http.ResponseWriter, r *http.Request
|
|||||||
res.Msg = string(buf)
|
res.Msg = string(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// POST /api/proxy/:name/kick
|
||||||
|
// Kick the client (frpc) that owns the proxy with given name.
|
||||||
|
func (svr *Service) apiKickProxyByName(w http.ResponseWriter, r *http.Request) {
|
||||||
|
res := GeneralResponse{Code: 200}
|
||||||
|
params := mux.Vars(r)
|
||||||
|
name := params["name"]
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
log.Infof("http response [%s]: code [%d]", r.URL.Path, res.Code)
|
||||||
|
w.WriteHeader(res.Code)
|
||||||
|
if len(res.Msg) > 0 {
|
||||||
|
_, _ = w.Write([]byte(res.Msg))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
log.Infof("http request: [%s]", r.URL.Path)
|
||||||
|
|
||||||
|
if name == "" {
|
||||||
|
res.Code = 400
|
||||||
|
res.Msg = "proxy name required"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := svr.ctlManager.KickByProxyName(name); err != nil {
|
||||||
|
res.Code = 404
|
||||||
|
res.Msg = err.Error()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
res.Msg = "ok"
|
||||||
|
}
|
||||||
|
|
||||||
func (svr *Service) getProxyStatsByTypeAndName(proxyType string, proxyName string) (proxyInfo GetProxyStatsResp, code int, msg string) {
|
func (svr *Service) getProxyStatsByTypeAndName(proxyType string, proxyName string) (proxyInfo GetProxyStatsResp, code int, msg string) {
|
||||||
proxyInfo.Name = proxyName
|
proxyInfo.Name = proxyName
|
||||||
ps := mem.StatsCollector.GetProxiesByTypeAndName(proxyType, proxyName)
|
ps := mem.StatsCollector.GetProxiesByTypeAndName(proxyType, proxyName)
|
||||||
|
|||||||
Reference in New Issue
Block a user