Browse Source

change frp

master
godo 5 months ago
parent
commit
da5bea9f5c
  1. 2
      docs/Faq.md
  2. 60
      frontend/src/components/setting/LocalProxy.vue
  3. 11
      godo/cmd/main.go
  4. 1
      godo/model/init.go
  5. 19
      godo/model/local_proxy.go
  6. 2
      godo/proxy/frpc.go
  7. 242
      godo/proxy/local.go

2
docs/Faq.md

@ -30,6 +30,8 @@ daemon.json文件配置:
}
```
systemctl daemon-reload
systemctl restart docker
### linux版本如何做守护进程
- 下载web版

60
frontend/src/components/setting/LocalProxy.vue

@ -2,29 +2,63 @@
import { Plus } from '@element-plus/icons-vue'
import { ref, computed } from "vue";
import { OpenDirDialog } from "@/util/goutil";
import { getSystemConfig } from '@/system/config';
import { notifySuccess,notifyError } from '@/util/msg';
interface ProxyItem {
id: number;
port: string;
proxyType: string;
domain: string;
}
const localKey = "godoos_local_proxy"
const getProxies = (): ProxyItem[] => {
const proxies = localStorage.getItem(localKey);
return proxies ? JSON.parse(proxies) : [];
};
const config = getSystemConfig();
const proxies = ref<ProxyItem[]>([]);
const total = ref(0)
const saveProxies = (proxies: ProxyItem[]) => {
localStorage.setItem(localKey, JSON.stringify(proxies));
const fetchProxies = async () => {
try {
const response = await fetch(config.apiUrl + "/api/v1/proxy/list");
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
if (data.proxies && Array.isArray(data.proxies)) {
proxies.value = data.proxies;
total.value = data.total;
} else {
console.error('Invalid data format:', data);
}
} catch (error) {
console.error('Failed to fetch proxies:', error);
}
};
onMounted(async () => {
await fetchProxies();
});
const saveProxies = (data: ProxyItem) => {
//localStorage.setItem(localKey, JSON.stringify(proxies));
fetch(config.apiUrl + '/api/proxy/add', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
}).then(res => {
if (!res.ok) {
notifyError('保存代理失败');
}else{
notifySuccess('保存代理成功');
}
});
};
const proxies = ref<ProxyItem[]>(getProxies());
const proxyData = ref<ProxyItem>({
// const proxies = ref<ProxyItem[]>(getProxies());
const proxyInit = {
id: Date.now(),
port: "",
proxyType: "http",
domain: "",
});
}
const proxyData = ref<ProxyItem>(proxyInit);
const types = ref([
{ label: 'HTTP', value: 'http' },
{ label: 'Udp', value: 'udp' },
@ -37,9 +71,9 @@ const pwdRef = ref<any>(null);
const addProxy = () => {
if (pwdRef.value.validate()) {
proxies.value.push({ ...proxyData.value });
saveProxies(proxies.value);
saveProxies(proxyData.value);
proxyDialogShow.value = false;
proxyData.value = { id: Date.now(), port: "", domain: "", proxyType: "http" };
proxyData.value = proxyInit;
}
};
@ -56,7 +90,7 @@ const updateProxy = () => {
proxies.value[index] = { ...proxyData.value };
saveProxies(proxies.value);
proxyDialogShow.value = false;
proxyData.value = { id: Date.now(), port: "", domain: "", proxyType: "http" };
proxyData.value = proxyInit;
isEditing.value = false;
}
}

11
godo/cmd/main.go

@ -25,6 +25,8 @@ import (
"godo/files"
"godo/libs"
"godo/localchat"
db "godo/model"
"godo/proxy"
"godo/store"
"godo/sys"
"godo/webdav"
@ -46,6 +48,8 @@ func OsStart() {
log.Fatalf("InitOsSystem error: %v", err)
return
}
db.InitDB()
proxy.InitProxyHandlers()
webdav.InitWebdav()
router := mux.NewRouter()
router.Use(recoverMiddleware)
@ -149,6 +153,13 @@ func OsStart() {
ieRouter.HandleFunc("/back", store.HandleBack).Methods(http.MethodGet)
ieRouter.HandleFunc("/forward", store.HandleForward).Methods(http.MethodGet)
ieRouter.HandleFunc("/refresh", store.HandleRefresh).Methods(http.MethodGet)
//注册代理路由
proxyRouter := router.PathPrefix("/proxy").Subrouter()
proxyRouter.HandleFunc("/local/create", proxy.CreateLocalProxyHandler).Methods(http.MethodPost)
proxyRouter.HandleFunc("/local/delete", proxy.DeleteLocalProxyHandler).Methods(http.MethodGet)
proxyRouter.HandleFunc("/local/get", proxy.GetLocalProxyHandler).Methods(http.MethodGet)
proxyRouter.HandleFunc("/local/list", proxy.GetLocalProxiesHandler).Methods(http.MethodGet)
proxyRouter.HandleFunc("/local/update", proxy.UpdateLocalProxyHandler).Methods(http.MethodPost)
// 注册根路径的处理函数
distFS, _ := fs.Sub(deps.Frontendassets, "dist")

1
godo/model/init.go

@ -21,6 +21,7 @@ func InitDB() {
db.AutoMigrate(&SysDisk{})
// 初始化 SysDisk 记录
initSysDisk(db)
db.AutoMigrate(&LocalProxy{})
db.AutoMigrate(&SysUser{})
db.AutoMigrate(&ClientUser{})
db.AutoMigrate(&ServerUser{})

19
godo/model/local_proxy.go

@ -12,3 +12,22 @@ type LocalProxy struct {
func (*LocalProxy) TableName() string {
return "local_proxy"
}
// GetLocalProxies 获取所有 LocalProxy,支持分页
func GetLocalProxies(page, limit int) ([]LocalProxy, int64, error) {
var proxies []LocalProxy
var total int64
// 先计算总数
if err := Db.Model(&LocalProxy{}).Count(&total).Error; err != nil {
return nil, 0, err
}
// 再进行分页查询
offset := (page - 1) * limit
if err := Db.Limit(limit).Offset(offset).Find(&proxies).Error; err != nil {
return nil, 0, err
}
return proxies, total, nil
}

2
godo/sys/frpc.go → godo/proxy/frpc.go

@ -1,4 +1,4 @@
package sys
package proxy
import (
"fmt"

242
godo/proxy/local.go

@ -0,0 +1,242 @@
package proxy
import (
"encoding/json"
"fmt"
"godo/model"
"net"
"net/http"
"net/http/httputil"
"net/url"
"strconv"
)
// 创建 LocalProxy 的 HTTP 处理函数
func CreateLocalProxyHandler(w http.ResponseWriter, r *http.Request) {
var lp model.LocalProxy
err := json.NewDecoder(r.Body).Decode(&lp)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
err = model.Db.Create(&lp).Error
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(lp)
}
// GetLocalProxiesHandler 获取所有 LocalProxy 的 HTTP 处理函数
func GetLocalProxiesHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
// 获取查询参数 page 和 limit
pageStr := r.URL.Query().Get("page")
limitStr := r.URL.Query().Get("limit")
page, err := strconv.Atoi(pageStr)
if err != nil || page < 1 {
page = 1
}
limit, err := strconv.Atoi(limitStr)
if err != nil || limit < 1 {
limit = 10
}
// 定义响应结构体
type ProxyResponse struct {
Proxies []model.LocalProxy `json:"proxies"`
Total int64 `json:"total"`
}
// 修改处理函数
proxies, total, err := model.GetLocalProxies(page, limit)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
response := ProxyResponse{
Proxies: proxies,
Total: total,
}
if err := json.NewEncoder(w).Encode(response); err != nil {
http.Error(w, "Failed to encode response", http.StatusInternalServerError)
return
}
}
// GetLocalProxyHandler 获取单个 LocalProxy 的 HTTP 处理函数
func GetLocalProxyHandler(w http.ResponseWriter, r *http.Request) {
idStr := r.URL.Query().Get("id")
id, err := strconv.Atoi(idStr)
if err != nil {
http.Error(w, "Invalid ID", http.StatusBadRequest)
return
}
var proxy model.LocalProxy
err = model.Db.First(&proxy, uint(id)).Error
if err != nil {
http.Error(w, err.Error(), http.StatusNotFound)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(proxy)
}
// UpdateLocalProxyHandler 更新 LocalProxy 的 HTTP 处理函数
func UpdateLocalProxyHandler(w http.ResponseWriter, r *http.Request) {
var lp model.LocalProxy
err := json.NewDecoder(r.Body).Decode(&lp)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
err = model.Db.Model(&model.LocalProxy{}).Where("id = ?", lp.ID).Updates(lp).Error
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(lp)
}
// DeleteLocalProxyHandler 删除 LocalProxy 的 HTTP 处理函数
func DeleteLocalProxyHandler(w http.ResponseWriter, r *http.Request) {
idStr := r.URL.Query().Get("id")
id, err := strconv.Atoi(idStr)
if err != nil {
http.Error(w, "Invalid ID", http.StatusBadRequest)
return
}
err = model.Db.Delete(&model.LocalProxy{}, uint(id)).Error
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusNoContent)
}
// 初始化代理处理函数
func InitProxyHandlers() {
proxies, _, err := model.GetLocalProxies(1, 1000) // 获取所有代理配置
if err != nil {
fmt.Println("Failed to get local proxies:", err)
return
}
for _, proxy := range proxies {
switch proxy.ProxyType {
case "http":
go func(p model.LocalProxy) {
httpProxyHandler(p)
}(proxy)
case "udp":
// UDP 转发的处理逻辑
go func(p model.LocalProxy) {
udpProxyHandler(p)
}(proxy)
case "file":
http.Handle(fmt.Sprintf("/file/%d/", proxy.Port), http.StripPrefix(fmt.Sprintf("/file/%d/", proxy.Port), http.FileServer(http.Dir(proxy.Domain))))
fmt.Printf("Setting up file server for port %d at %s\n", proxy.Port, proxy.Domain)
default:
fmt.Printf("Unknown proxy type: %s\n", proxy.ProxyType)
}
}
}
// HTTP 代理处理函数
func httpProxyHandler(proxy model.LocalProxy) {
remote, err := url.Parse(proxy.Domain)
if err != nil {
fmt.Printf("Failed to parse remote URL for port %d: %v\n", proxy.Port, err)
return
}
reverseProxy := httputil.NewSingleHostReverseProxy(remote)
// 启动 HTTP 服务器并监听指定端口
server := &http.Server{
Addr: fmt.Sprintf(":%d", proxy.Port),
Handler: reverseProxy,
}
fmt.Printf("Starting HTTP proxy on port %d and forwarding to %s:%d\n", proxy.Port, proxy.Domain, proxy.Port)
if err := server.ListenAndServe(); err != nil {
fmt.Printf("Failed to start HTTP proxy on port %d: %v\n", proxy.Port, err)
}
}
// UDP 代理处理函数
func udpProxyHandler(proxy model.LocalProxy) {
localAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf(":%d", proxy.Port))
if err != nil {
fmt.Printf("Failed to resolve local UDP address for port %d: %v\n", proxy.Port, err)
return
}
remoteAddr, err := net.ResolveUDPAddr("udp", proxy.Domain)
if err != nil {
fmt.Printf("Failed to resolve remote UDP address for port %d: %v\n", proxy.Port, err)
return
}
conn, err := net.ListenUDP("udp", localAddr)
if err != nil {
fmt.Printf("Failed to listen on UDP port %d: %v\n", proxy.Port, err)
return
}
defer conn.Close()
buffer := make([]byte, 1024)
for {
n, addr, err := conn.ReadFromUDP(buffer)
if err != nil {
fmt.Printf("Failed to read from UDP: %v\n", err)
continue
}
remoteConn, err := net.DialUDP("udp", nil, remoteAddr)
if err != nil {
fmt.Printf("Failed to dial remote UDP: %v\n", err)
continue
}
_, err = remoteConn.Write(buffer[:n])
if err != nil {
fmt.Printf("Failed to write to remote UDP: %v\n", err)
continue
}
// 读取远程服务器的响应并转发回客户端
n, err = remoteConn.Read(buffer)
if err != nil {
fmt.Printf("Failed to read from remote UDP: %v\n", err)
continue
}
_, err = conn.WriteToUDP(buffer[:n], addr)
if err != nil {
fmt.Printf("Failed to write to client UDP: %v\n", err)
continue
}
}
}
Loading…
Cancel
Save