commit f1597a6d576881f44cbd0b2825c12ad93e59a93b
| author | 斟酌 鵬兄 <tgckpg@gmail.com> |
| date | 2026-05-21T14:40:31Z |
| subject | Added SOCKS5 support |
commit f1597a6d576881f44cbd0b2825c12ad93e59a93b
Author: 斟酌 鵬兄 <tgckpg@gmail.com>
Date: 2026-05-21T14:40:31Z
Added SOCKS5 support
---
deploy/freedns-webhook/templates/deployment.yaml | 2 +-
freedns/freedns.go | 90 +++++++++++++++++++-----
image.Makefile | 32 +++++++++
3 files changed, 106 insertions(+), 18 deletions(-)
diff --git a/deploy/freedns-webhook/templates/deployment.yaml b/deploy/freedns-webhook/templates/deployment.yaml
index 44a5a89..1c99dcd 100644
--- a/deploy/freedns-webhook/templates/deployment.yaml
+++ b/deploy/freedns-webhook/templates/deployment.yaml
@@ -23,7 +23,7 @@ spec:
serviceAccountName: {{ include "freedns-webhook.fullname" . }}
containers:
- name: {{ .Chart.Name }}
- image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
+ image: "{{ .Values.image.repository }}{{- if .Values.image.digest }}@{{ .Values.image.digest }}{{- else }}:{{ .Values.image.tag }}{{- end }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
args:
- --v=2
diff --git a/freedns/freedns.go b/freedns/freedns.go
index 55c771c..ffe2771 100755
--- a/freedns/freedns.go
+++ b/freedns/freedns.go
@@ -1,16 +1,21 @@
package freedns
import (
+ "context"
"errors"
"fmt"
- "io/ioutil"
+ "io"
+ "log"
+ "net"
"net/http"
"net/url"
+ "os"
"strconv"
"strings"
logf "github.com/cert-manager/cert-manager/pkg/logs"
"golang.org/x/net/html"
+ "golang.org/x/net/proxy"
)
type FreeDNSOperations interface {
@@ -27,6 +32,10 @@ type FreeDNS struct {
LoggedOut bool
}
+type contextDialer interface {
+ DialContext(ctx context.Context, network, address string) (net.Conn, error)
+}
+
const URI_LOGIN = "https://freedns.afraid.org/zc.php?step=2"
const URI_DOMAIN = "https://freedns.afraid.org/domain/"
const URI_ADD_RECORD = "https://freedns.afraid.org/subdomain/save.php?step=2"
@@ -41,43 +50,89 @@ func GetDomainFromZone(Zone string) string {
return strings.Join(_segs, ".")
}
-func _HttpRequest(method string, url string, PostData url.Values, ExCookie *http.Cookie) (*http.Response, string, error) {
- client := http.Client{
+func newHTTPClient() (*http.Client, error) {
+ transport := http.DefaultTransport.(*http.Transport).Clone()
+
+ socksAddr := os.Getenv("SOCKS5_PROXY")
+ if socksAddr != "" {
+ log.Printf("using SOCKS5 proxy from SOCKS5_PROXY: %s", redactProxyAddr(socksAddr))
+ dialer, err := proxy.SOCKS5("tcp", socksAddr, nil, proxy.Direct)
+ if err != nil {
+ return nil, err
+ }
+
+ ctxDialer, ok := dialer.(interface {
+ DialContext(ctx context.Context, network, address string) (net.Conn, error)
+ })
+ if !ok {
+ return nil, fmt.Errorf("SOCKS5 dialer does not support DialContext")
+ }
+
+ transport.Proxy = nil
+ transport.DialContext = ctxDialer.DialContext
+ } else {
+ transport.Proxy = http.ProxyFromEnvironment
+ }
+
+ return &http.Client{
+ Transport: transport,
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
+ }, nil
+}
+
+func redactProxyAddr(addr string) string {
+ u, err := url.Parse(addr)
+ if err == nil && u.User != nil {
+ u.User = url.UserPassword("xxxxx", "xxxxx")
+ return u.String()
}
- var req *http.Request
- var err error
+ return addr
+}
- if method == "GET" {
- req, err = http.NewRequest(method, url, nil)
- } else if method == "POST" {
- req, err = http.NewRequest(method, url, strings.NewReader(PostData.Encode()))
- req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
- } else {
- return nil, "", errors.New("Method + \"" + method + "\" is not supported")
+func _HttpRequest(method string, reqURL string, postData url.Values, exCookie *http.Cookie) (*http.Response, string, error) {
+ client, err := newHTTPClient()
+ if err != nil {
+ return nil, "", err
+ }
+
+ var body io.Reader
+
+ switch method {
+ case http.MethodGet:
+ body = nil
+
+ case http.MethodPost:
+ body = strings.NewReader(postData.Encode())
+
+ default:
+ return nil, "", fmt.Errorf("method %q is not supported", method)
}
+ req, err := http.NewRequest(method, reqURL, body)
if err != nil {
return nil, "", err
}
req.Header.Set("User-Agent", "github.com/tgckpg/cert-manager-webhook-freedns (2022.03.15)")
- if ExCookie != nil {
- req.AddCookie(ExCookie)
+ if method == http.MethodPost {
+ req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
+ }
+
+ if exCookie != nil {
+ req.AddCookie(exCookie)
}
resp, err := client.Do(req)
if err != nil {
return resp, "", err
}
+ defer resp.Body.Close()
- respData, err := ioutil.ReadAll(resp.Body)
- resp.Body.Close()
-
+ respData, err := io.ReadAll(resp.Body)
if err != nil {
return resp, "", err
}
@@ -97,6 +152,7 @@ func (dnsObj *FreeDNS) Login(Username string, Password string) error {
if err != nil {
return err
}
+ fmt.Println(err)
if strings.Contains(respString, "Invalid UserID/Pass") {
return errors.New("Invalid UserID/Pass")
diff --git a/image.Makefile b/image.Makefile
new file mode 100644
index 0000000..acffdcf
--- /dev/null
+++ b/image.Makefile
@@ -0,0 +1,32 @@
+IMAGE_NAME := penguinade/cert-manager-webhook-freedns
+IMAGE_TAG := dev
+
+BUILDX_BUILDER := container-builder
+
+ensure-buildx:
+ @if ! docker buildx inspect $(BUILDX_BUILDER) >/dev/null 2>&1; then \
+ echo "Creating buildx builder $(BUILDX_BUILDER)..."; \
+ docker buildx create \
+ --name $(BUILDX_BUILDER) \
+ --driver docker-container \
+ --driver-opt network=host \
+ --bootstrap --use; \
+ else \
+ echo "Using existing buildx builder $(BUILDX_BUILDER)"; \
+ docker buildx use $(BUILDX_BUILDER); \
+ fi
+
+build: ensure-buildx
+ docker buildx build \
+ --platform linux/amd64,linux/arm64 \
+ -f Dockerfile \
+ -t $(IMAGE_NAME):$(IMAGE_TAG) .
+
+push: ensure-buildx
+ docker buildx build \
+ --platform linux/amd64,linux/arm64 \
+ -f Dockerfile \
+ -t $(IMAGE_NAME):$(IMAGE_TAG) \
+ --push .
+
+.PHONY: push