140 lines
3.5 KiB
Go
140 lines
3.5 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"net"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// Config 结构体存储配置信息
|
|
type Config struct {
|
|
Global struct {
|
|
LT map[string]string // 存储本地地址到目标地址的映射
|
|
LU map[string]string // 存储本地地址到目标地址的映射
|
|
}
|
|
}
|
|
|
|
// isValidHostname 验证主机名格式
|
|
func isValidHostname(hostname string) bool {
|
|
if len(hostname) > 255 || hostname == "" {
|
|
return false
|
|
}
|
|
for _, part := range strings.Split(hostname, ".") {
|
|
if len(part) == 0 || len(part) > 63 {
|
|
return false
|
|
}
|
|
for _, c := range part {
|
|
if !((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '-') {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
// parseAddress 解析并验证地址字符串
|
|
func parseAddress(address string) (string, int, error) {
|
|
host, portStr, err := net.SplitHostPort(address)
|
|
if err != nil {
|
|
return "", 0, fmt.Errorf("地址格式错误: %s (格式应为 host:port)", address)
|
|
}
|
|
|
|
port, err := strconv.Atoi(portStr)
|
|
if err != nil || port < 1 || port > 65535 {
|
|
return "", 0, fmt.Errorf("无效的端口号: %s", address)
|
|
}
|
|
|
|
host = strings.Trim(host, "[]") // 去除 IPv6 方括号
|
|
if net.ParseIP(host) == nil && !isValidHostname(host) {
|
|
return "", 0, fmt.Errorf("无效的主机名或 IP: %s", address)
|
|
}
|
|
|
|
return host, port, nil
|
|
}
|
|
|
|
// parseConfig 解析配置文件
|
|
func parseConfig(filename string) (Config, error) {
|
|
var config Config
|
|
config.Global.LT = make(map[string]string)
|
|
config.Global.LU = make(map[string]string)
|
|
var currentSection string
|
|
|
|
file, err := os.Open(filename)
|
|
if err != nil {
|
|
return config, err
|
|
}
|
|
defer file.Close()
|
|
|
|
scanner := bufio.NewScanner(file)
|
|
for scanner.Scan() {
|
|
line := strings.TrimSpace(scanner.Text())
|
|
if line == "" || strings.HasPrefix(line, "//") || strings.HasPrefix(line, "#") {
|
|
continue
|
|
}
|
|
|
|
if strings.HasSuffix(line, "{") {
|
|
currentSection = strings.Fields(line)[0]
|
|
continue
|
|
}
|
|
if line == "}" {
|
|
currentSection = ""
|
|
continue
|
|
}
|
|
|
|
parts := strings.SplitN(line, "=", 2)
|
|
if len(parts) != 2 {
|
|
continue
|
|
}
|
|
|
|
key := strings.TrimSpace(parts[0])
|
|
value := strings.TrimSpace(strings.TrimSuffix(parts[1], ";"))
|
|
|
|
if currentSection == "global" && key == "LT" {
|
|
lsParts := strings.SplitN(value, "->", 2)
|
|
if len(lsParts) == 2 {
|
|
localAddr := strings.TrimSpace(lsParts[0])
|
|
targetAddr := strings.TrimSpace(lsParts[1])
|
|
|
|
if _, _, err := parseAddress(localAddr); err != nil {
|
|
return config, fmt.Errorf("本地地址格式错误: %s", localAddr)
|
|
}
|
|
if _, _, err := parseAddress(targetAddr); err != nil {
|
|
return config, fmt.Errorf("目标地址格式错误: %s", targetAddr)
|
|
}
|
|
|
|
config.Global.LT[localAddr] = targetAddr
|
|
} else {
|
|
return config, fmt.Errorf("LT 配置格式错误: %s", value)
|
|
}
|
|
}
|
|
|
|
if currentSection == "global" && key == "LU" {
|
|
lsParts := strings.SplitN(value, "->", 2)
|
|
if len(lsParts) == 2 {
|
|
localAddr := strings.TrimSpace(lsParts[0])
|
|
targetAddr := strings.TrimSpace(lsParts[1])
|
|
|
|
if _, _, err := parseAddress(localAddr); err != nil {
|
|
return config, fmt.Errorf("本地地址格式错误: %s", localAddr)
|
|
}
|
|
if _, _, err := parseAddress(targetAddr); err != nil {
|
|
return config, fmt.Errorf("目标地址格式错误: %s", targetAddr)
|
|
}
|
|
|
|
config.Global.LU[localAddr] = targetAddr
|
|
} else {
|
|
return config, fmt.Errorf("LU 配置格式错误: %s", value)
|
|
}
|
|
}
|
|
}
|
|
|
|
if err := scanner.Err(); err != nil {
|
|
return config, err
|
|
}
|
|
|
|
return config, nil
|
|
}
|