OpenVPN 서버: 스크립트를 통해 정적 IP 주소 할당
18045 단어 openvpn
client-config-dir
지시문을 사용하여 클라이언트별 구성 파일을 통해 정적 구성을 사용하는 대신 동적으로 수행할 수 있는 방법을 찾았습니다. 나는 결국 client-connect
스크립트를 사용하여 데이터베이스에서 직접 IP를 할당하기로 결정했지만 문서가 다소 부족하다는 것을 알았습니다.몇 가지 다른 작업에 사용되는
clients
라는 데이터베이스 테이블이 있으며 기본적으로 다음과 같은 구조를 갖습니다.CREATE TABLE clients (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
ip inet NOT NULL,
CONSTRAINT clients_name_unique UNIQUE (name),
CONSTRAINT clients_ip_unique UNIQUE (ip)
);
클라이언트가 연결되면 X509 일반 이름을 기반으로 IP 주소를 찾아 클라이언트에 푸시하려고 합니다.
client-config-dir
옵션을 사용하는 경우 클라이언트의 일반 이름과 동일한 이름으로 구성된 디렉토리 내에 파일을 만들고 ifconfig-push IP_ADDRESS SUBNET_MASK
를 사용하여 이 작업을 수행합니다. 이는 주 서버 구성 파일 내의 주석에 언급된 것을 포함하여 매우 잘 문서화된 접근 방식입니다. 문제는 내가 이미 데이터베이스 테이블을 유지 관리할 때 이러한 파일을 유지 관리하는 데 추가 작업이 추가된다는 것입니다.다른 접근 방식은 OpenVPN 서버가 다양한 이벤트를 처리할 때 실행하도록 구성할 수 있는 가능한 많은 스크립트 중 하나(특히
client-connect
스크립트)를 사용하는 것입니다.옵션을 탐색하는 동안 StackExchange 네트워크에서 예제 스크립트를 찾는 사람들의 몇 가지 질문을 발견했고 결국 Reference manual for OpenVPN 2.4 및 보다 구체적으로 Scripting and environment variables section 을 찾았습니다. 이렇게 하면 각 유형의 스크립트에 사용할 수 있는 환경 변수를 설명할 수 있지만 연결 구성 자체에 실제로 영향을 미칠 수 있는 방법을 설명하는 데는 별 도움이 되지 않습니다.
OpenVPN 서버는 실제로 클라이언트에 대한 구성을 나타내는 파일의 경로인 구성된 스크립트에 인수를 전달하는 것으로 나타났습니다. 따라서 흐름은 기본적으로 다음과 같이 끝납니다.
common_name
환경 변수가 설정된 경우 가져옵니다. common_name
값을 사용하여 클라이언트의 IP 주소를 찾습니다. ifconfig-push IP_ADDRESS SUBNET_MASK
를 파일에 씁니다. 하지만 이 접근 방식에 대한 몇 가지 참고 사항이 있습니다.
결국 내가 택한 경로는 bash 스크립트를 호출하는 비교적 간단한 Go였습니다. bash 스크립트는
/usr/local/bin/resolve-vpn-ip.sh
에 저장되고 실행 가능합니다.#!/usr/bin/env bash
set -Eeuo pipefail
DSN="postgresql://..."
/usr/local/bin/resolve-vpn-ip -db="$DSN" "$@"
실제
/usr/local/bin/resolve-vpn-ip
프로그램은 Go 바이너리입니다. 동일한 데이터베이스와 통신하는 다른 시스템의 일부 공통 코드를 재사용하기 때문입니다. 기본적으로 다음과 같이 요약됩니다.package main
import (
"context"
"flag"
"fmt"
"log"
"net"
"os"
"os/signal"
"syscall"
"github.com/jackc/pgx/v4"
)
func main() {
log.SetFlags(log.LstdFlags)
flags := flag.NewFlagSet("resolve-vpn-ip", flag.ExitOnError)
dsnFlag := flags.String("db", "", "the database connection string to use to connect to the database")
if err := flags.Parse(os.Args[1:]); err != nil {
flags.PrintDefaults()
os.Exit(0)
}
remainingArgs := flags.Args()
if len(remainingArgs) < 1 {
log.Println("no arguments after flags, OpenVPN did not pass in a configuration file")
os.Exit(0)
}
commonName, found := os.LookupEnv("common_name")
if !found || commonName == "" {
log.Println("common_name environment variable is not set or is empty")
os.Exit(0)
}
log.Printf("getting IP address for client: %s\n", commonName)
ctx, _ := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
ip, err := getIpForClient(ctx, *dsnFlag, commonName)
if err != nil {
log.Printf("error getting IP address for client: %s; error: %s\n", commonName, err)
os.Exit(0)
}
f, err := os.OpenFile(remainingArgs[0], os.O_APPEND|os.O_WRONLY|os.O_CREATE, os.ModePerm)
if err != nil {
log.Printf(
"failed to open config file for client: %s; file: %s; error: %s\n",
commonName,
remainingArgs[0],
err,
)
os.Exit(0)
}
defer func(toClose *os.File) {
_ = toClose.Close()
}(f)
if _, err = fmt.Fprintf(f, "ifconfig-push %s 255.255.255.0\n", ip.String()); err != nil {
log.Printf(
"failed to write to config file for client: %s; file: %s; error: %s\n",
commonName,
remainingArgs[0],
err,
)
os.Exit(0)
}
}
func getIpForClient(ctx context.Context, dsn, commonName string) (*net.IP, error) {
conn, err := pgx.Connect(ctx, dsn)
if err != nil {
return nil, err
}
defer func(c *pgx.Conn) {
_ = conn.Close(ctx)
}(conn)
var ip net.IP
err = conn.QueryRow(ctx, `SELECT ip FROM clients WHERE name = $1;`, commonName).Scan(&ip)
switch err {
case nil:
return &ip, nil
case pgx.ErrNoRows:
return nil, fmt.Errorf("no rows found for client: %s", commonName)
default:
return nil, fmt.Errorf("error getting ip for client: %s; error: %w", commonName, err)
}
}
OpenVPN 서버 구성 파일에서 다음과 같은 내용을 추가하여 내 스크립트를 실행하도록 서버를 구성할 수 있습니다.
client-connect "/usr/local/bin/resolve-vpn-ip.sh"
그리고
journalctl -f /usr/local/bin/resolve-vpn-ip
와 같은 명령을 실행하여 journald를 통해 언제든지 내 로그를 추적할 수 있습니다.
Reference
이 문제에 관하여(OpenVPN 서버: 스크립트를 통해 정적 IP 주소 할당), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/euantorano/openvpn-server-assigning-static-ip-addresses-via-a-script-1ief텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)