mirror of
https://github.com/Sagit-chu/flvx.git
synced 2026-09-28 07:36:38 +08:00
185 lines
5.9 KiB
Plaintext
185 lines
5.9 KiB
Plaintext
现在我已经找到了完整的入口IP生成流程。让我整理并返回关键信息:
|
|
|
|
---
|
|
|
|
## 入口IP生成流程分析
|
|
|
|
### 1. `buildTunnelInIP` 函数 (创建/更新隧道时)
|
|
|
|
**位置**: `go-backend/internal/http/handler/mutations.go:2112-2152`
|
|
|
|
```go
|
|
func buildTunnelInIP(inNodes []tunnelRuntimeNode, nodes map[int64]*nodeRecord, ipPreference string) string {
|
|
set := make(map[string]struct{})
|
|
ordered := make([]string, 0)
|
|
preferV6 := strings.TrimSpace(ipPreference) == "v6"
|
|
for _, inNode := range inNodes {
|
|
node := nodes[inNode.NodeID]
|
|
if node == nil {
|
|
continue
|
|
}
|
|
v4 := strings.TrimSpace(node.ServerIPv4) // 从节点获取 IPv4
|
|
v6 := strings.TrimSpace(node.ServerIPv6) // 从节点获取 IPv6
|
|
var addrs []string
|
|
if preferV6 {
|
|
if v6 != "" { addrs = append(addrs, v6) }
|
|
if v4 != "" { addrs = append(addrs, v4) }
|
|
} else {
|
|
if v4 != "" { addrs = append(addrs, v4) }
|
|
if v6 != "" { addrs = append(addrs, v6) }
|
|
}
|
|
if len(addrs) == 0 {
|
|
if v := strings.TrimSpace(node.ServerIP); v != "" { // fallback 到 ServerIP
|
|
addrs = append(addrs, v)
|
|
}
|
|
}
|
|
// ... 去重后拼接
|
|
}
|
|
return strings.Join(ordered, ",")
|
|
}
|
|
```
|
|
|
|
**调用位置**:
|
|
- 隧道创建: `mutations.go:496`
|
|
- 隧道更新: `mutations.go:693`
|
|
|
|
---
|
|
|
|
### 2. `resolveForwardIngress` 函数 (查询转发时)
|
|
|
|
**位置**: `go-backend/internal/store/repo/repository.go:2727-2796`
|
|
|
|
```go
|
|
func resolveForwardIngress(db *gorm.DB, forwardID int64, tunnelID int64) (string, sql.NullInt64, error) {
|
|
// 1. 首先从 tunnel 表获取 in_ip (由 buildTunnelInIP 生成)
|
|
var tunnelInIP sql.NullString
|
|
db.Model(&model.Tunnel{}).Select("in_ip").Where("id = ?", tunnelID).Limit(1).Scan(&tunnelInIP)
|
|
|
|
// 2. 从 forward_port + node 表获取端口和节点IP
|
|
type fpRow struct {
|
|
Port sql.NullInt64
|
|
ServerIP sql.NullString
|
|
}
|
|
var fpRows []fpRow
|
|
err := db.Model(&model.ForwardPort{}).
|
|
Select("forward_port.port, node.server_ip").
|
|
Joins("LEFT JOIN node ON node.id = forward_port.node_id").
|
|
Where("forward_port.forward_id = ?", forwardID).
|
|
Order("forward_port.id ASC").
|
|
Find(&fpRows).Error
|
|
|
|
// 3. 组装入口地址
|
|
// - 如果 tunnel.in_ip 存在: "ip1:port,ip2:port..."
|
|
// - 否则使用 forward_port 关联的 node.server_ip: "ip:port"
|
|
// ...
|
|
}
|
|
```
|
|
|
|
**调用位置**:
|
|
- `repository.go:495` - 用户转发列表
|
|
- `repository.go:730` - 管理员转发列表
|
|
|
|
---
|
|
|
|
### 3. `forward_port` 表与节点IP关联
|
|
|
|
**模型定义**: `go-backend/internal/store/model/model.go:50-57`
|
|
|
|
```go
|
|
type ForwardPort struct {
|
|
ID int64 `gorm:"primaryKey;autoIncrement"`
|
|
ForwardID int64 `gorm:"column:forward_id;not null"`
|
|
NodeID int64 `gorm:"column:node_id;not null"` // 关联到 node.id
|
|
Port int `gorm:"not null"`
|
|
}
|
|
```
|
|
|
|
**关联查询** (在 `resolveForwardIngress` 中):
|
|
```sql
|
|
SELECT forward_port.port, node.server_ip
|
|
FROM forward_port
|
|
LEFT JOIN node ON node.id = forward_port.node_id
|
|
WHERE forward_port.forward_id = ?
|
|
ORDER BY forward_port.id ASC
|
|
```
|
|
|
|
---
|
|
|
|
### 4. 转发创建API入口分配流程
|
|
|
|
**入口函数**: `go-backend/internal/http/handler/mutations.go:1108-1194`
|
|
|
|
```go
|
|
func (h *Handler) forwardCreate(w http.ResponseWriter, r *http.Request) {
|
|
// 1. 获取隧道入口节点IDs
|
|
entryNodes, _ := h.tunnelEntryNodeIDs(tunnelID) // line 1162
|
|
|
|
// 2. 获取或选择入口端口
|
|
port := asInt(req["inPort"], 0)
|
|
if port <= 0 {
|
|
port = h.pickTunnelPort(tunnelID) // 自动分配端口 (line 1157)
|
|
}
|
|
|
|
// 3. 创建转发记录 + forward_port 记录
|
|
forwardID, err := h.repo.CreateForwardTx(..., entryNodes, port, ...) // line 1179
|
|
}
|
|
```
|
|
|
|
**`CreateForwardTx`**: `go-backend/internal/store/repo/repository_mutations.go:1171-1209`
|
|
```go
|
|
func (r *Repository) CreateForwardTx(..., entryNodeIDs []int64, port int, ...) (int64, error) {
|
|
// 创建 forward 记录
|
|
// 为每个入口节点创建 forward_port 记录
|
|
for _, nodeID := range entryNodeIDs {
|
|
fp := model.ForwardPort{
|
|
ForwardID: forwardID,
|
|
NodeID: nodeID, // 入口节点ID
|
|
Port: port, // 入口端口
|
|
}
|
|
tx.Create(&fp)
|
|
}
|
|
}
|
|
```
|
|
|
|
**入口节点获取**: `repository_mutations.go:535-548`
|
|
```go
|
|
func (r *Repository) TunnelEntryNodeIDs(tunnelID int64) ([]int64, error) {
|
|
// 从 chain_tunnel 表查询 chain_type = 1 (入口) 的节点
|
|
r.db.Model(&model.ChainTunnel{}).
|
|
Where("tunnel_id = ? AND chain_type = ?", tunnelID, "1").
|
|
Order("inx ASC, id ASC").
|
|
Pluck("node_id", &ids)
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 关键修改位置
|
|
|
|
| 需求 | 修改文件 | 行号 | 说明 |
|
|
|------|----------|------|------|
|
|
| **修改隧道入口IP生成逻辑** | `mutations.go` | 2112-2152 | `buildTunnelInIP` 函数,控制IPv4/IPv6优先级和组合 |
|
|
| **修改转发入口IP解析** | `repository.go` | 2727-2796 | `resolveForwardIngress`,控制入口地址格式 |
|
|
| **修改端口自动分配** | `mutations.go` | 2901-2964 | `pickTunnelPort`,控制端口范围选择 |
|
|
| **修改入口节点关联** | `repository_mutations.go` | 1196-1205 | `CreateForwardTx` 中的 forward_port 创建 |
|
|
| **节点IP来源** | `model.go` | 516-531 | `NodeRecord` 结构体 |
|
|
| **节点IP存储** | `model.go` | 59-65 | `Node` 模型: `ServerIP`, `ServerIPV4`, `ServerIPV6` |
|
|
|
|
---
|
|
|
|
## 入口IP数据流
|
|
|
|
```
|
|
1. 节点注册 → Node表存储 server_ip, server_ip_v4, server_ip_v6
|
|
|
|
2. 创建隧道:
|
|
chain_tunnel (入口节点) → buildTunnelInIP() → tunnel.in_ip 字段
|
|
|
|
3. 创建转发:
|
|
隧道入口节点IDs → forward_port(forward_id, node_id, port)
|
|
|
|
4. 查询转发入口:
|
|
forward_port JOIN node → resolveForwardIngress()
|
|
├─ 优先使用 tunnel.in_ip (多IP组合)
|
|
└─ 否则用 forward_port 关联的 node.server_ip
|
|
``` |