package main // import "vpngate"
import (
"bufio"
"bytes"
"encoding/base64"
"encoding/json"
"flag"
"fmt"
"io"
"net/http"
"os"
"os/exec"
"path/filepath"
"sort"
"strconv"
"strings"
"time"
)
const (
configFile = "vpn_server.config"
)
type VPNServer struct {
Hostname string
IP string
Port string
Country string
Ping int
Score int
Config string
}
var (
// scoreMinimum = 2000000
scoreMinimum = 1
pingMinimum = 15
connectionName = "VPNgateAutoConnection"
rank int
disconnect bool
notUseIPs = []string{}
)
func extractIPAndPort(config string) (string, string) {
scanner := bufio.NewScanner(strings.NewReader(config))
for scanner.Scan() {
line := scanner.Text()
if strings.HasPrefix(line, "remote ") {
parts := strings.Fields(line)
if len(parts) >= 3 {
return parts[1], parts[2]
}
}
}
return "", ""
}
func findBestVPNServer(rank int) (*VPNServer, error) {
var err error
var servers []*VPNServer
response, err := http.Get(vpnGateURL)
if err != nil {
return nil, fmt.Errorf("서버 목록 가져오기 실패: %v", err)
}
defer response.Body.Close()
scanner := bufio.NewScanner(response.Body)
for scanner.Scan() {
line := scanner.Text()
splits := strings.Split(line, ",")
if len(splits) < 15 {
continue
}
ping, err := strconv.Atoi(splits[3])
if err != nil || ping > pingMinimum {
continue
}
score, err := strconv.Atoi(splits[2])
if err != nil || score < scoreMinimum {
continue
}
decodedConfig, err := base64.StdEncoding.DecodeString(splits[14])
if err != nil {
continue
}
ip, port := extractIPAndPort(string(decodedConfig))
server := &VPNServer{
Hostname: splits[0],
IP: ip,
Port: port,
Country: splits[5],
Ping: ping,
Score: score,
Config: string(decodedConfig),
}
servers = append(servers, server)
}
if len(servers) == 0 {
return nil, fmt.Errorf("적합한 서버를 찾을 수 없음")
}
if rank > len(servers) {
return nil, fmt.Errorf("지정된 순위의 서버를 찾을 수 없음")
}
sort.Slice(servers, func(i, j int) bool {
return servers[i].Ping < servers[j].Ping
})
// for i, s := range servers {
// // fmt.Println(" ip, ping, score:", ip, ping, score)
// fmt.Println(" i, ip, ping, score:", i+1, s.IP, s.Ping, s.Score)
// }
return servers[rank-1], nil
}
func saveVPNConfig(config string) (string, error) {
absPath, err := filepath.Abs(configFile)
if err != nil {
return "", err
}
err = os.WriteFile(absPath, []byte(config), 0664)
return absPath, err
}
func connectVPN(server *VPNServer) error {
cmd := exec.Command("vpncmd", "/client")
var input bytes.Buffer
input.WriteString("\n") // localhost
// input.WriteString("2\n") // Client mode
input.WriteString("AccountCreate " + connectionName + " /hub:VPNGATE /username:vpn /nicname:VPN\n")
input.WriteString(server.IP + ":" + server.Port + "\n")
input.WriteString("AccountConnect " + connectionName + "\n")
input.WriteString("exit\n")
cmd.Stdin = &input
done := make(chan error, 1)
var output []byte
go func() {
var err error
output, err = cmd.CombinedOutput()
done <- err
}()
select {
case err := <-done:
fmt.Printf("VPN 연결 출력:\n%s", string(output))
if err != nil {
return fmt.Errorf("VPN 연결 실패: %s - %v", string(output), err)
}
return nil
case <-time.After(30 * time.Second):
return fmt.Errorf("VPN 연결 시간 초과")
}
}
func getPublicIP() (string, error) {
apis := []string{
}
client := &http.Client{Timeout: 2 * time.Second}
for _, url := range apis {
resp, err := client.Get(url)
if err != nil {
continue
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
fmt.Println("ReadAll:", err)
continue
}
var ipData map[string]interface{}
err = json.Unmarshal(body, &ipData)
if err != nil {
fmt.Println("Unmarshall:", err)
continue
}
if ip, ok := ipData["ip"].(string); ok {
return ip, nil
}
}
return "", fmt.Errorf("IP 주소를 찾을 수 없음")
}
func connectMain(rank int) error {
var err error
kurrentIP, err := getPublicIP()
if err != nil {
return fmt.Errorf("IP 주소 확인 실패: %v", err)
}
fmt.Println("현재 IP:", kurrentIP)
previousIP := kurrentIP
fmt.Println("VPN Gate 서버 목록 가져오는 중...")
bestServer, err := findBestVPNServer(rank)
if err != nil {
return fmt.Errorf("서버 선택 실패: %v", err)
}
fmt.Printf("선택된 서버: %s (%s) - %s:%s\n",
bestServer.Hostname,
bestServer.Country,
bestServer.IP,
bestServer.Port,
)
configPath, err := saveVPNConfig(bestServer.Config)
if err != nil {
return fmt.Errorf("서버 설정 저장 실패: %v", err)
}
fmt.Printf("서버 설정이 %s에 저장되었습니다.", configPath)
fmt.Println("VPN 연결 시도 중...")
err = connectVPN(bestServer)
if err != nil {
return fmt.Errorf("VPN 연결 실패: %v", err)
}
fmt.Println("\nVPN에 연결되었습니다! 아이피 할당을 시도합니다.")
count := 0
for {
kurrentIP, err = getPublicIP()
if err != nil {
return fmt.Errorf("IP 주소 확인 실패: %v", err)
}
if kurrentIP != previousIP {
fmt.Printf("\nIP 주소가 변경되었습니다: %s", kurrentIP)
previousIP = kurrentIP
break
}
fmt.Print(".")
count++
if count > 5 {
fmt.Println("VPN 연결 실패! 설정을 삭제합니다.")
return fmt.Errorf("VPN 연결 시간 초과")
}
time.Sleep(time.Duration(1 * time.Second))
}
return nil
}
func disconnectAndDelete() error {
// configFile 파일 삭제
if err := os.Remove(configFile); err != nil {
return err
}
cmd := exec.Command("vpncmd", "/client")
var input bytes.Buffer
input.WriteString("\n") // localhost
// input.WriteString("2\n") // Client mode
input.WriteString("AccountDisconnect " + connectionName + "\n")
input.WriteString("AccountDelete " + connectionName + "\n")
input.WriteString("exit\n")
cmd.Stdin = &input
done := make(chan error, 1)
var output []byte
go func() {
var err error
output, err = cmd.CombinedOutput()
done <- err
}()
select {
case err := <-done:
fmt.Printf("VPN 연결 해제 출력:\n%s", string(output))
if err != nil {
return fmt.Errorf("VPN 연결 해제 실패: %s - %v", string(output), err)
}
return nil
case <-time.After(30 * time.Second):
return fmt.Errorf("VPN 연결 해제 시간 초과")
}
}
func init() {
flag.IntVar(&rank, "rank", 1, "VPN server rank to connect (default: 1)")
flag.BoolVar(&disconnect, "disconnect", false, "Disconnect and delete VPN connection")
flag.Parse()
}
func main() {
var err error
if disconnect {
if err := disconnectAndDelete(); err != nil {
fmt.Printf("VPN 연결 해제 실패: %v", err)
return
}
fmt.Println("VPN 연결이 성공적으로 해제되었습니다!")
return
}
count := 0
for {
err = connectMain(rank)
if err == nil {
break
}
count++
rank++
fmt.Println("VPN 연결 실패! 설정을 삭제합니다.", count)
if err := disconnectAndDelete(); err != nil {
fmt.Printf("VPN 설정 삭제 실패: %v", err)
return
}
if count >= 10 {
fmt.Println("VPN 연결 실패! 참조하는 서버를 찾을 수 없습니다.")
return
}
time.Sleep(time.Duration(250 * time.Millisecond))
}
}
vpn이다. vpn
중공 1등 인민 주인님들꼐서 사랑하시는 바둑언어인 golang을 깔고 중공사랑 실천하자.
일제 무른모 vpngate 도 필요해.
cu는 왜 금칙어야 시발거
ㅇㅅㅇ
님 49.165님?
VPN Client>현재 IP: 49.165VPN Gate 서버 목록 가져오는 중...선택된 서버: vpn891883062 (Japan) - 131.147vpngate\vpn_server.config에 저장되었습니다.VPN 연결 시도 중...VPN Client>AccountConnect command - Start Connection to VPN Server using VPN Connection SettingThe command completed successfully.VPN Client>VPN에 연결되었습니다! 아이피 할당을 시도합니다..IP 주소가 변경되었습니다: 131.147ㅇㅅㅇ