Skip to content

添加Windows服务管理和事件日志集成#5004

Closed
donmor wants to merge 50 commits intofatedier:devfrom
donmor:patch-2
Closed

添加Windows服务管理和事件日志集成#5004
donmor wants to merge 50 commits intofatedier:devfrom
donmor:patch-2

Conversation

@donmor
Copy link
Copy Markdown

@donmor donmor commented Sep 29, 2025

实现 #2468 ,可直接使用sc.exe(cmd)/New-Service(powershell)/注册表将frps或frpc注册为服务(可使用LocalService、服务账户等提高安全性)

计划实现:

  • 加入golang.org/x/sys/windows/svc包,使frps和frpc符合Windows服务程序规范
  • 加入golang.org/x/sys/windows/svc/eventlog包,为Logger添加Windows事件日志后端(可使用Windows事件查看器查看)
  • 为每种日志输出添加独有的event ID(需要定义更多eid;需要改golib那边) 暂时搁置
  • 为frpc添加pause/continue支持(并同时reload代理配置)
  • 日志事件源存在检测和自动安装(使用powershell命令,自动添加需要UAC提权)
  • 服务安装/卸载命令(在启动参数前插入install以安装,非-c的参数和install命令间需插入--;使用uninstall命令以卸载;会同时注册/移除事件源;需在管理员cmd/powershell中执行;默认使用LocalSystem身份,restricted模式使用NT AUTHORITY\LocalService和受限SID)

@donmor donmor force-pushed the patch-2 branch 2 times, most recently from db50946 to 48d1add Compare October 5, 2025 08:20
@github-actions
Copy link
Copy Markdown

PRs go stale after 14d of inactivity. Stale PRs rot after an additional 3d of inactivity and eventually close.

@donmor
Copy link
Copy Markdown
Author

donmor commented Oct 20, 2025

自顶

@wuai1024
Copy link
Copy Markdown

wuai1024 commented Oct 23, 2025

这个不需要frp来程序实现, win 可以用 winsw , linux 可以使用 systemd 来管理。

例如这样:

image

@github-actions
Copy link
Copy Markdown

github-actions bot commented Nov 7, 2025

PRs go stale after 14d of inactivity. Stale PRs rot after an additional 3d of inactivity and eventually close.

@donmor
Copy link
Copy Markdown
Author

donmor commented Nov 7, 2025

自顶

@github-actions
Copy link
Copy Markdown

PRs go stale after 14d of inactivity. Stale PRs rot after an additional 3d of inactivity and eventually close.

@donmor
Copy link
Copy Markdown
Author

donmor commented Nov 22, 2025

自顶

@github-actions
Copy link
Copy Markdown

github-actions bot commented Dec 8, 2025

PRs go stale after 14d of inactivity. Stale PRs rot after an additional 3d of inactivity and eventually close.

@donmor
Copy link
Copy Markdown
Author

donmor commented Dec 8, 2025

自顶

@donmor donmor force-pushed the patch-2 branch 2 times, most recently from a0384f4 to 0a04e9e Compare December 17, 2025 07:49
@github-actions
Copy link
Copy Markdown

github-actions bot commented Jan 1, 2026

PRs go stale after 14d of inactivity. Stale PRs rot after an additional 3d of inactivity and eventually close.

@donmor
Copy link
Copy Markdown
Author

donmor commented Jan 15, 2026

挖一下,已经rebase并适配新的unsafe特性

@github-actions
Copy link
Copy Markdown

PRs go stale after 14d of inactivity. Stale PRs rot after an additional 3d of inactivity and eventually close.

fatedier and others added 25 commits March 9, 2026 16:08
…tedier#5200)

Fix two bugs in TCPGroup.Listen():
- Release acquired port when net.Listen fails to prevent port leak
- Use realPort instead of port for net.Listen to ensure consistency
  between port manager records and actual listening port
…dier#5202)

Fix connection leaks in multiple error paths across client and server:
- server/proxy/http: close tmpConn when WithEncryption fails
- client/proxy: close localConn when ProxyProtocol WriteTo fails
- client/visitor/sudp: close visitorConn on all error paths in getNewVisitorConn
- client/visitor/xtcp: close tunnelConn when WithEncryption fails
- client/visitor/xtcp: close lConn when NewKCPConnFromUDP fails
- pkg/plugin/client/unix_domain_socket: close localConn and connInfo.Conn when WriteTo fails, close connInfo.Conn when DialUnix fails
- pkg/plugin/client/tls2raw: close tlsConn when Handshake or Dial fails
…edier#5203)

- pkg/nathole/nathole.go: add pool.PutBuf(buf) on ReadFromUDP error
  and DecodeMessageInto error paths in waitDetectMessage
- pkg/proto/udp/udp.go: add defer pool.PutBuf(buf) in writerFn to
  ensure buffer is returned when the goroutine exits
- pkg/util/net/websocket.go: store ln parameter in struct to prevent
  nil pointer panic when Addr() is called
- pkg/auth/oidc.go: replace unsynchronized []string with map + RWMutex
  for subjectsFromLogin to fix data race across concurrent connections
…dier#5205)

- pkg/transport/tls.go: check AppendCertsFromPEM return value and
  return clear error when CA file contains no valid PEM certificates
- pkg/plugin/client/http2http.go: set ReadHeaderTimeout to 60s to
  match other plugins and prevent slow header attacks
- pkg/plugin/client/http2https.go: same ReadHeaderTimeout fix
…e value copy (fatedier#5206)

In AddPrefix, the loop `for _, p := range l.prefixes` creates a copy
of each element. Assignments to p.Value and p.Priority only modify
the local copy, not the original slice element, causing updates to
existing prefixes to be silently lost.

This affects client/service.go where AddPrefix is called with
Name:"runID" on reconnection — the old runID value would persist
in log output instead of being updated to the new one.

Fix by using index-based access `l.prefixes[i]` to modify the
original slice element, and add break since prefix names are unique.
…licate loop (fatedier#5207)

The Run() method had two nearly identical loop blocks for registering
custom domains and subdomain, with the same group/non-group registration
logic copy-pasted (~30 lines of duplication).

Consolidate by collecting all domains into a single slice first, then
iterating once with the shared registration logic. Also fixes a minor
inconsistency where the custom domain block used routeConfig.Domain in
CanonicalAddr but the subdomain block used tmpRouteConfig.Domain.
…tedier#5208)

Consolidate the separate custom-domain loop and subdomain block into a
single unified loop, matching the pattern already applied to HTTPProxy
in PR fatedier#5207. No behavioral change.
- strings.CutPrefix instead of HasPrefix+TrimPrefix (naming, legacy)
- slices.Contains instead of manual loop (plugin/server)
- min/max builtins instead of manual comparisons (nathole)
…atedier#5210)

- slices.SortedFunc + maps.Values + cmp.Compare instead of manual
  map-to-slice collection + sort.Slice (source/aggregator.go)
- strings.CutSuffix instead of HasSuffix+TrimSuffix, and deduplicate
  error handling in BandwidthQuantity.UnmarshalString (types/types.go)
…er#5212)

* client/proxy: extract wrapWorkConn to deduplicate UDP/SUDP connection wrapping

Move the repeated rate-limiting, encryption, and compression wrapping
logic from UDPProxy and SUDPProxy into a shared BaseProxy.wrapWorkConn
method, reducing ~18 lines of duplication in each proxy type.

* client/proxy: unify work conn wrapping with pooled compression for all proxy types

Refactor wrapWorkConn to accept encKey parameter and return
(io.ReadWriteCloser, recycleFn, error), enabling HandleTCPWorkConnection
to reuse the same limiter/encryption/compression pipeline.

Switch all proxy types from WithCompression to WithCompressionFromPool.
TCP non-plugin path calls recycleFn via defer after Join; plugin and
UDP/SUDP paths skip recycle (objects are GC'd safely, per golib contract).
…atedier#5213)

- Replace duplicate parseBasicAuth with existing httppkg.ParseBasicAuth
- Extract buildDomains helper in BaseProxy for HTTP/HTTPS/TCPMux proxies
- Extract toProxyStats helper to deduplicate ProxyStats construction
- Extract startVisitorListener helper in BaseProxy for STCP/SUDP proxies
- Extract acceptLoop helper in BaseVisitor for STCP/XTCP visitors
…atedier#5214)

- pkg/nathole: add RLock when reading clientCfgs map in PreCheck path
  to prevent concurrent map read/write crash
- server/proxy: fix error variable shadowing in GetWorkConnFromPool
  that could return a closed connection with nil error
- pkg/util/net: check ListenUDP error before spawning goroutines
  and assign readConn to struct field so Close() works correctly
…fatedier#5217)

Replace 10 positional parameters in NewControl() with a single
SessionContext struct, matching the client-side pattern. This also
eliminates the post-construction mutation of clientRegistry and
removes two TODO comments.
…on (fatedier#5218)

Extract closeProxy() helper to eliminate duplicated 4-step cleanup
sequence (Close, PxyManager.Del, metrics, plugin notify) between
worker() and CloseProxy().

Extract loginUserInfo() helper to eliminate 4 repeated plugin.UserInfo
constructions using LoginMsg fields.

Optimize worker() to snapshot and clear the proxies map under lock,
then perform cleanup outside the lock to reduce lock hold time.
…fatedier#5219)

Extract two shared helpers to eliminate duplicated code across STCP,
SUDP, and XTCP visitors:

- dialRawVisitorConn: handles ConnectServer + NewVisitorConn handshake
  (auth, sign key, 10s read deadline, error check)
- wrapVisitorConn: handles encryption + pooled compression wrapping,
  returning a recycleFn for pool resource cleanup

SUDP is upgraded from WithCompression to WithCompressionFromPool,
aligning with the pooled compression used by STCP and XTCP.
…lookup (fatedier#5221)

Remove 4 redundant pointer map write-backs in OpenConnection,
CloseConnection, AddTrafficIn, and AddTrafficOut since the map stores
pointers and mutations are already visible without reassignment.

Optimize GetProxiesByTypeAndName from O(n) full map scan to O(1) direct
map lookup by proxy name.
…ssues (fatedier#5222)

* server/group: refactor group package with shared abstractions and fix concurrency issues

Extract common patterns into reusable components:
- groupRegistry[G]: generic concurrent map for group lifecycle management
- baseGroup: shared plumbing for listener-based groups (TCP, HTTPS, TCPMux)
- Listener: unified virtual listener replacing 3 identical implementations

Fix concurrency issues:
- Stale-pointer race: isCurrent check + errGroupStale + controller retry loops
- Worker generation safety: pass realLn and acceptCh as params instead of reading mutable fields
- Connection leak: close conn on worker panic recovery path
- ABBA deadlock in HTTP UnRegister: consistent lock ordering (group.mu -> registry.mu)
- Round-robin overflow in HTTPGroup: use unsigned modulo

Add unit tests (17 tests) for registry, listener, and baseGroup.
Add TCPMux group load balancing e2e test.

* server/group: replace tautological assertion with require.NotPanics

* server/group: remove blank line between doc comment and type declaration
…ss checks (fatedier#5223)

Replace the fixed 500ms sleep after each frps startup in RunProcesses
with a TCP dial-based readiness check that polls the server bind port.
This reduces the e2e suite wall time from ~97s to ~43s.

Also simplify the RunProcesses API to accept a single server template
string instead of a slice, matching how every call site uses it.
…ier#5225)

* test/e2e: optimize RunFrps/RunFrpc with process exit detection

Refactor Process to track subprocess lifecycle via a done channel,
replacing direct cmd.Wait() in Stop() to avoid double-Wait races.
RunFrps/RunFrpc now use select on the done channel instead of fixed
sleeps, allowing short-lived processes (verify, startup failures) to
return immediately while preserving existing timeout behavior for
long-running daemons.

* test/e2e: guard Process against double-Start and Stop-before-Start

Add started flag to prevent double-Start panics and allow Stop to
return immediately when the process was never started. Use sync.Once
for closing the done channel as defense-in-depth against double close.
@kilo-code-bot
Copy link
Copy Markdown

kilo-code-bot bot commented Mar 9, 2026

Code Review Summary

Status: 1 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 0
Issue Details (click to expand)

WARNING

File Line Issue
web/frps/src/views/ProxyDetail.vue 345 Proxy detail lookup can return the wrong proxy when names are duplicated across types.
Other Observations (not in diff)

Issues found in unchanged code that cannot receive inline comments:

File Line Issue
server/http/controller.go 192 GET /api/proxies/{name} resolves proxies only by name, so the new detail page can display the wrong proxy when two proxies of different types share a name.
Files Reviewed (10 files)
  • client/config_manager.go - 0 issues
  • pkg/config/load.go - 0 issues
  • pkg/config/source/store.go - 0 issues
  • pkg/config/source/aggregator.go - 0 issues
  • pkg/config/v1/decode.go - 0 issues
  • pkg/config/v1/visitor.go - 0 issues
  • client/http/controller.go - 0 issues
  • cmd/frpc/sub/root.go - 0 issues
  • web/frps/src/views/Proxies.vue - 0 issues
  • web/frps/src/views/ProxyDetail.vue - 1 issue

Fix these issues in Kilo Cloud

@donmor
Copy link
Copy Markdown
Author

donmor commented Mar 9, 2026

此PR似乎已无法正常变基到最新dev分支,将会重新创建

@donmor
Copy link
Copy Markdown
Author

donmor commented Mar 9, 2026

已重新创建为#5227

@donmor donmor closed this Mar 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants