You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求可直接使用的带REST HTTP API的Golang HTTP端口转发代理服务程序

基于Golang的HTTP端口转发代理服务器(带REST API)

功能特性

  • 动态端口转发:通过REST API添加/删除TCP流量转发规则
  • 并发安全:使用互斥锁管理转发规则,支持多API请求并发操作
  • 轻量高效:基于Golang原生net包实现,性能优异

完整可运行代码

package main

import (
	"encoding/json"
	"io"
	"log"
	"net"
	"net/http"
	"sync"
)

// ForwardRule 存储端口转发规则
type ForwardRule struct {
	LocalPort  int    `json:"local_port"`
	TargetAddr string `json:"target_addr"`
	listener   net.Listener
}

var (
	forwardRules = make(map[int]*ForwardRule)
	rulesMutex   sync.Mutex
	apiPort      = 8080 // REST API监听端口
)

func main() {
	// 注册API路由
	http.HandleFunc("/add", handleAddRule)
	http.HandleFunc("/remove", handleRemoveRule)
	http.HandleFunc("/list", handleListRules)

	log.Printf("REST API server starting on :%d", apiPort)
	log.Fatal(http.ListenAndServe(":"+string(rune(apiPort+'0')), nil))
}

// handleAddRule 添加新的转发规则
func handleAddRule(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(w, "only POST method allowed", http.StatusMethodNotAllowed)
		return
	}

	var rule ForwardRule
	if err := json.NewDecoder(r.Body).Decode(&rule); err != nil {
		http.Error(w, "invalid request body: "+err.Error(), http.StatusBadRequest)
		return
	}

	rulesMutex.Lock()
	defer rulesMutex.Unlock()

	if _, exists := forwardRules[rule.LocalPort]; exists {
		http.Error(w, "local port already in use", http.StatusConflict)
		return
	}

	// 启动本地端口监听
	listener, err := net.Listen("tcp", ":"+string(rune(rule.LocalPort+'0')))
	if err != nil {
		http.Error(w, "failed to listen on local port: "+err.Error(), http.StatusInternalServerError)
		return
	}

	rule.listener = listener
	forwardRules[rule.LocalPort] = &rule

	// 启动转发协程
	go startForwarding(&rule)

	w.WriteHeader(http.StatusCreated)
	json.NewEncoder(w).Encode(map[string]string{"status": "success", "message": "forward rule added"})
}

// handleRemoveRule 删除指定转发规则
func handleRemoveRule(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodDelete {
		http.Error(w, "only DELETE method allowed", http.StatusMethodNotAllowed)
		return
	}

	var req struct {
		LocalPort int `json:"local_port"`
	}
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		http.Error(w, "invalid request body: "+err.Error(), http.StatusBadRequest)
		return
	}

	rulesMutex.Lock()
	defer rulesMutex.Unlock()

	rule, exists := forwardRules[req.LocalPort]
	if !exists {
		http.Error(w, "forward rule not found", http.StatusNotFound)
		return
	}

	// 关闭监听
	if err := rule.listener.Close(); err != nil {
		log.Printf("warning: failed to close listener on port %d: %v", req.LocalPort, err)
	}

	delete(forwardRules, req.LocalPort)
	w.WriteHeader(http.StatusOK)
	json.NewEncoder(w).Encode(map[string]string{"status": "success", "message": "forward rule removed"})
}

// handleListRules 返回所有当前转发规则
func handleListRules(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodGet {
		http.Error(w, "only GET method allowed", http.StatusMethodNotAllowed)
		return
	}

	rulesMutex.Lock()
	defer rulesMutex.Unlock()

	// 构造返回的规则列表(不含listener)
	var rules []ForwardRule
	for _, rule := range forwardRules {
		rules = append(rules, ForwardRule{
			LocalPort:  rule.LocalPort,
			TargetAddr: rule.TargetAddr,
		})
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(rules)
}

// startForwarding 处理端口转发逻辑
func startForwarding(rule *ForwardRule) {
	log.Printf("starting forward from :%d to %s", rule.LocalPort, rule.TargetAddr)
	defer log.Printf("stopped forward from :%d", rule.LocalPort)

	for {
		conn, err := rule.listener.Accept()
		if err != nil {
			// 监听关闭时退出
			return
		}

		go handleConnection(conn, rule.TargetAddr)
	}
}

// handleConnection 处理单个连接的流量转发
func handleConnection(localConn net.Conn, targetAddr string) {
	defer localConn.Close()

	targetConn, err := net.Dial("tcp", targetAddr)
	if err != nil {
		log.Printf("failed to connect to target %s: %v", targetAddr, err)
		return
	}
	defer targetConn.Close()

	// 双向转发流量
	var wg sync.WaitGroup
	wg.Add(2)

	go func() {
		defer wg.Done()
		io.Copy(targetConn, localConn)
	}()

	go func() {
		defer wg.Done()
		io.Copy(localConn, targetConn)
	}()

	wg.Wait()
}

使用说明

  1. 编译程序:
    将上述代码保存为main.go,执行编译命令:

    go build -o proxy-server main.go
    
  2. 启动服务器:

    ./proxy-server
    

    默认REST API监听8080端口,可修改代码中apiPort变量调整。

  3. API调用示例:

    • 添加转发规则:
      curl -X POST -H "Content-Type: application/json" -d '{"local_port": 8081, "target_addr": "example.com:80"}' http://localhost:8080/add
      
    • 删除转发规则:
      curl -X DELETE -H "Content-Type: application/json" -d '{"local_port": 8081}' http://localhost:8080/remove
      
    • 查看所有规则:
      curl http://localhost:8080/list
      

内容的提问来源于stack exchange,提问作者zerohh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 14:30:25