Инициализация проекта
Всем привет :)
This commit is contained in:
177
internal/wireguard/portforward.go
Normal file
177
internal/wireguard/portforward.go
Normal file
@@ -0,0 +1,177 @@
|
||||
package wireguard
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os/exec"
|
||||
|
||||
"wg-panel/internal/database"
|
||||
)
|
||||
|
||||
// isPortAvailable проверяет доступен ли порт
|
||||
func isPortAvailable(db *database.Database, port int, protocol string) bool {
|
||||
protocols := []string{protocol}
|
||||
if protocol == "both" {
|
||||
protocols = []string{"tcp", "udp", "both"}
|
||||
}
|
||||
|
||||
for _, client := range db.Clients {
|
||||
for _, pf := range client.PortForwards {
|
||||
if pf.Port == port {
|
||||
// Проверяем конфликт протоколов
|
||||
if pf.Protocol == "both" || protocol == "both" {
|
||||
return false
|
||||
}
|
||||
for _, p := range protocols {
|
||||
if pf.Protocol == p {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// AddPortForward добавляет проброс порта для клиента
|
||||
func AddPortForward(db *database.Database, client *database.Client, port int, protocol, description string) error {
|
||||
// Проверяем что порт свободен
|
||||
if !isPortAvailable(db, port, protocol) {
|
||||
return fmt.Errorf("порт %d/%s уже используется", port, protocol)
|
||||
}
|
||||
|
||||
// Добавляем в список
|
||||
portForward := database.PortForward{
|
||||
Port: port,
|
||||
Protocol: protocol,
|
||||
Description: description,
|
||||
}
|
||||
client.PortForwards = append(client.PortForwards, portForward)
|
||||
|
||||
// Применяем правила iptables если клиент активен
|
||||
if client.Enabled {
|
||||
if err := applyPortForwardRules(client, portForward); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// updatePortForward обновляет проброс порта
|
||||
func updatePortForward(client *database.Client, port int, protocol, newDescription string) error {
|
||||
for i, pf := range client.PortForwards {
|
||||
if pf.Port == port && pf.Protocol == protocol {
|
||||
client.PortForwards[i].Description = newDescription
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("проброс порта не найден")
|
||||
}
|
||||
|
||||
// RemovePortForward удаляет проброс порта
|
||||
func RemovePortForward(client *database.Client, port int, protocol string) error {
|
||||
// Находим и удаляем проброс
|
||||
for i, pf := range client.PortForwards {
|
||||
if pf.Port == port && pf.Protocol == protocol {
|
||||
// Удаляем правила iptables
|
||||
if client.Enabled {
|
||||
removePortForwardRules(client, pf)
|
||||
}
|
||||
|
||||
// Удаляем из списка
|
||||
client.PortForwards = append(client.PortForwards[:i], client.PortForwards[i+1:]...)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("проброс порта не найден")
|
||||
}
|
||||
|
||||
// applyPortForwardRules применяет правила iptables для проброса порта
|
||||
func applyPortForwardRules(client *database.Client, pf database.PortForward) error {
|
||||
log.Printf(" 🔀 Применяю проброс порта %d (%s)", pf.Port, pf.Protocol)
|
||||
|
||||
netInterface := database.GetDefaultInterface()
|
||||
|
||||
protocols := []string{pf.Protocol}
|
||||
if pf.Protocol == "both" {
|
||||
protocols = []string{"tcp", "udp"}
|
||||
}
|
||||
|
||||
for _, proto := range protocols {
|
||||
commands := [][]string{
|
||||
// DNAT только для пакетов приходящих с внешнего интерфейса
|
||||
{"iptables", "-t", "nat", "-A", "PREROUTING", "-i", netInterface, "-p", proto,
|
||||
"--dport", fmt.Sprintf("%d", pf.Port), "-j", "DNAT",
|
||||
"--to-destination", fmt.Sprintf("%s:%d", client.Address, pf.Port)},
|
||||
|
||||
// Разрешаем FORWARD для этого порта
|
||||
{"iptables", "-I", "FORWARD", "1", "-p", proto, "-d", client.Address,
|
||||
"--dport", fmt.Sprintf("%d", pf.Port), "-j", "ACCEPT"},
|
||||
}
|
||||
|
||||
for _, cmdArgs := range commands {
|
||||
cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...)
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
log.Printf(" ⚠️ Ошибка: %v (output: %s)", err, string(output))
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.Printf(" ✅ Проброс порта настроен")
|
||||
return nil
|
||||
}
|
||||
|
||||
// removePortForwardRules удаляет правила iptables для проброса порта
|
||||
func removePortForwardRules(client *database.Client, pf database.PortForward) error {
|
||||
netInterface := database.GetDefaultInterface()
|
||||
|
||||
protocols := []string{pf.Protocol}
|
||||
if pf.Protocol == "both" {
|
||||
protocols = []string{"tcp", "udp"}
|
||||
}
|
||||
|
||||
for _, proto := range protocols {
|
||||
commands := [][]string{
|
||||
{"iptables", "-t", "nat", "-D", "PREROUTING", "-i", netInterface, "-p", proto,
|
||||
"--dport", fmt.Sprintf("%d", pf.Port), "-j", "DNAT",
|
||||
"--to-destination", fmt.Sprintf("%s:%d", client.Address, pf.Port)},
|
||||
|
||||
{"iptables", "-D", "FORWARD", "-p", proto, "-d", client.Address,
|
||||
"--dport", fmt.Sprintf("%d", pf.Port), "-j", "ACCEPT"},
|
||||
}
|
||||
|
||||
for _, cmdArgs := range commands {
|
||||
cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...)
|
||||
cmd.Run() // Игнорируем ошибки при удалении
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ApplyAllPortForwards применяет все пробросы портов для клиента
|
||||
func ApplyAllPortForwards(client *database.Client) error {
|
||||
if !client.Enabled {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, pf := range client.PortForwards {
|
||||
if err := applyPortForwardRules(client, pf); err != nil {
|
||||
log.Printf(" ⚠️ Ошибка проброса порта %d: %v", pf.Port, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// removeAllPortForwards удаляет все пробросы портов для клиента
|
||||
func removeAllPortForwards(client *database.Client) error {
|
||||
for _, pf := range client.PortForwards {
|
||||
removePortForwardRules(client, pf)
|
||||
}
|
||||
return nil
|
||||
}
|
Reference in New Issue
Block a user