{"id":18602791,"url":"https://github.com/obgnail/go-frp","last_synced_at":"2025-04-10T19:31:08.470Z","repository":{"id":44331854,"uuid":"409038302","full_name":"obgnail/go-frp","owner":"obgnail","description":"重写 frp 的内网穿透玩具","archived":false,"fork":false,"pushed_at":"2022-05-20T08:38:16.000Z","size":55,"stargazers_count":8,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-25T03:34:05.391Z","etag":null,"topics":["frp","golang","nat-traversal","network","proxy-server"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/obgnail.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-09-22T02:23:59.000Z","updated_at":"2025-01-10T01:12:55.000Z","dependencies_parsed_at":"2022-09-01T16:51:41.158Z","dependency_job_id":null,"html_url":"https://github.com/obgnail/go-frp","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/obgnail%2Fgo-frp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/obgnail%2Fgo-frp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/obgnail%2Fgo-frp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/obgnail%2Fgo-frp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/obgnail","download_url":"https://codeload.github.com/obgnail/go-frp/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248281395,"owners_count":21077423,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["frp","golang","nat-traversal","network","proxy-server"],"created_at":"2024-11-07T02:12:33.901Z","updated_at":"2025-04-10T19:31:06.994Z","avatar_url":"https://github.com/obgnail.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"## 模仿frp的基于代理的内网穿透玩具\n\n因为原版frp的可读性很差，故重构。\n\n\n\n## Usage\n\nServer：\n\n```go\nfunc main() {\n\tcommonProxyServer, err := NewProxyServer(\n\t\t\"common\",\n\t\t\"0.0.0.0\",\n\t\t8888,\n\t\t[]*consts.AppInfo{\n\t\t\t{Name: \"SSH\", Password: \"\"},\n\t\t\t{Name: \"HTTP\", Password: \"\"},\n\t\t},\n\t)\n\tif err != nil {\n\t\tlog.Error(errors.ErrorStack(err))\n\t}\n\tcommonProxyServer.Serve()\n}\n```\n\n```bash\ncd frps/\ngo run *.go\n```\n\n\n\nClient：\n\n```go\nfunc main() {\n\tNewProxyClient(\n\t\t\"common\",\n\t\t5555,\n\t\t\"127.0.0.1\",\n\t\t8888,\n\t\t[]*consts.AppInfo{\n\t\t\t{Name: \"SSH\", LocalPort: 22, Password: \"\"},\n\t\t\t{Name: \"HTTP\", LocalPort: 7777, Password: \"\"},\n\t\t},\n\t).Run()\n}\n```\n\n```bash\ncd frpc/\ngo run *.go\n```\n\n\n\nUser：\n\n```bash\n# ssh: \n# proxy 6000 to 22\nssh -o 6000 yourComputerName@127.0.0.1\n\n# http: \n# proxy 5000 to 7777\npython3 -m http.server 7777\ncurl 127.0.0.1:5000\n```\n\n## sequenceDiagram\n\n```mermaid\nsequenceDiagram\n    participant User\n    participant CommonServer\n    participant ProxyServer\n    participant CommonClient\n    participant ProxyClient\n\n    Note over CommonServer, CommonClient: 准备阶段\n    CommonServer -\u003e\u003e CommonServer: 监听BindPort\n    CommonClient -\u003e\u003e CommonClient: 构建ProxyClient对象\n    \n    Note over CommonServer, CommonClient: 初始化阶段\n    CommonClient -\u003e\u003e + CommonServer: 连接到Common conn，发送所有ProxyClient的信息\n    CommonServer -\u003e\u003e CommonServer: 根据ProxyName取出所有的ProxyServer对象，校验\n    CommonServer -\u003e\u003e ProxyServer: 通知每个ProxyServer开始监听各自的端口\n    ProxyServer -\u003e\u003e ProxyServer: 开启goroutine，监听ProxyConn，等待User连接\n    CommonServer -\u003e\u003e CommonServer: 开启goroutine，监听heartbeat\n    CommonServer --\u003e\u003e - CommonClient: 告知CommonClient所有ProxyServer的信息，表明Ready，可以进行代理\n    CommonClient -\u003e\u003e CommonClient: 存储ProxySever信息\n   \tpar par and loop\n   \t\tCommonClient -\u003e\u003e CommonServer: 发送heartbeat\n   \t\tCommonServer --\u003e\u003e CommonClient: 响应heartbeat\n   \tend\n    \n    Note over User, ProxyClient: 代理阶段\n    User -\u003e\u003e + ProxyServer: User连接ProxyServer，希望开始代理\n    ProxyServer -\u003e\u003e ProxyServer: 储存UserConn\n    ProxyServer -\u003e\u003e CommonServer: 通知CommonServer\u003cbr/\u003e将「希望开启代理」的信号传给CommonClient\n    CommonServer -\u003e\u003e CommonClient: 告知CommonClient「希望开启代理」\n    CommonClient -\u003e\u003e CommonClient: 从存储中找到「希望开启代理」的APP信息\n    CommonClient -\u003e\u003e ProxyClient: 开启本地端口\n    ProxyClient --\u003e\u003e CommonClient: 返回localConn\n    CommonClient -\u003e\u003e ProxyServer: 连接到ProxyServer\n    ProxyServer -\u003e\u003e ProxyServer: 1.校验ProxyClientConn和message\u003cbr/\u003e2.从存储中找到UserConn\n    par\n   \t\tProxyServer -\u003e\u003e ProxyServer: Join ProxyClientConn and UserConn\n   \tend\n\t\tProxyServer --\u003e\u003e CommonClient: 返回remoteConn\n\t\tpar\n   \t\tCommonClient -\u003e\u003e CommonClient: Join localConn and remoteConn\n   \tend\n    ProxyServer --\u003e\u003e - User: 返回\n```\n\n\n\n## 两个Join操作\n\n```mermaid\nsequenceDiagram\n    participant User(Mac)\n    participant ProxyServer(Tencent)\n    participant ProxyClient(Rasp)\n    participant UnixSocket(Rasp)\n\n\t\tNote over User(Mac), ProxyServer(Tencent): UserConn\n\t\tNote over ProxyServer(Tencent), ProxyClient(Rasp): ProxyClientConn\n\t\t\n\t\tNote over ProxyServer(Tencent), ProxyClient(Rasp): remoteConn\n\t\tNote over ProxyClient(Rasp), UnixSocket(Rasp): localConn\n```\n\n对于Tencent来说：\n\n- UserConn：表示来自于Mac的TCP连接。\n- ProxyClientConn：表示连接到Rasp某个服务的TCP连接。\n\n对于Rasp来说：\n\n- RemoteConn：表示来自于Tencent的TCP连接。\n- LocalConn：表示本机某个服务的UnixSocket连接。\n\n经过两个Join操作，ProxyClientConn、UserConn、remoteConn、UnixSocketConn都互相串通。也就实现了远程User与UnixSocket的连接，也就是Mac通过Tencent，连接到了Rasp。\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fobgnail%2Fgo-frp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fobgnail%2Fgo-frp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fobgnail%2Fgo-frp/lists"}