v5.0.68: TLSNextProto fix — disable HTTP/2 ALPN (DDoS-Guard EOF)
This commit is contained in:
@@ -507,7 +507,7 @@ func (c *UniversalClient) FindInstanceByDisplayName(ctx context.Context, service
|
||||
if len(found) == 0 {
|
||||
page := 1
|
||||
for {
|
||||
reqURL := fmt.Sprintf("%s?endpoint=/instances&page=%d&size=100", c.ApiEndpoint, page)
|
||||
reqURL := fmt.Sprintf("%s/instances?page=%d&size=100", c.ApiEndpoint, page)
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", reqURL, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -581,7 +581,7 @@ func (c *UniversalClient) FindInstanceByDisplayName(ctx context.Context, service
|
||||
}
|
||||
|
||||
func (c *UniversalClient) GetInstanceState(ctx context.Context, instanceUid string) (*InstanceStateResponse, error) {
|
||||
url := fmt.Sprintf("%s?endpoint=/instances/%s", c.ApiEndpoint, instanceUid)
|
||||
url := fmt.Sprintf("%s/instances/%s", c.ApiEndpoint, instanceUid)
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -627,7 +627,7 @@ func isInstanceDeleted(state *InstanceStateResponse) bool {
|
||||
// GetInstanceStateRaw получает состояние инстанса БЕЗ валидации статуса.
|
||||
// Используется для проверки ref-параметров: нужно читать даже deleted/suspended инстансы.
|
||||
func (c *UniversalClient) GetInstanceStateRaw(ctx context.Context, instanceUid string) (*InstanceStateResponse, error) {
|
||||
reqURL := fmt.Sprintf("%s?endpoint=/instances/%s", c.ApiEndpoint, instanceUid)
|
||||
reqURL := fmt.Sprintf("%s/instances/%s", c.ApiEndpoint, instanceUid)
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", reqURL, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -828,21 +828,15 @@ func (c *UniversalClient) doRequest(ctx context.Context, method, path string, pa
|
||||
body = bytes.NewBuffer(b)
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, method, c.ApiEndpoint, body)
|
||||
req, err := http.NewRequestWithContext(ctx, method, c.ApiEndpoint+path, body)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// ?endpoint= формат — как генератор, чтобы пройти DDoS-Guard
|
||||
q := req.URL.Query()
|
||||
q.Set("endpoint", path)
|
||||
req.URL.RawQuery = q.Encode()
|
||||
|
||||
req.Close = false
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("User-Agent", userAgent)
|
||||
req.Header.Set("Accept", "application/json, text/plain, */*")
|
||||
req.Header.Set("Accept-Language", "en-US,en;q=0.9")
|
||||
if body != nil {
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
}
|
||||
if c.ApiToken != "" {
|
||||
req.Header.Set("Authorization", "Bearer "+c.ApiToken)
|
||||
}
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
package provider
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -21,7 +17,6 @@ import (
|
||||
"github.com/hashicorp/terraform-plugin-framework/provider/schema"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
utls "github.com/refraction-networking/utls"
|
||||
)
|
||||
|
||||
var _ provider.Provider = &NubesProvider{}
|
||||
@@ -128,59 +123,12 @@ func (p *NubesProvider) Configure(ctx context.Context, req provider.ConfigureReq
|
||||
// HTTP transport: клонируем DefaultTransport чтобы сохранить системные настройки (proxy, timeouts).
|
||||
transport := http.DefaultTransport.(*http.Transport).Clone()
|
||||
transport.TLSHandshakeTimeout = 60 * time.Second
|
||||
transport.ForceAttemptHTTP2 = false
|
||||
|
||||
// utls: маскируем Go TLS под Firefox, чтобы пройти DDoS-Guard (JA3 fingerprint).
|
||||
// Стандартный crypto/tls и Chrome блокируются на deck-api-*.ngcloud.ru.
|
||||
transport.DialTLSContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
// Используем прокси если задан (HTTPS_PROXY) — без него API не доступен
|
||||
dialer := &net.Dialer{Timeout: 30 * time.Second}
|
||||
proxyFunc := transport.Proxy
|
||||
target := addr
|
||||
if proxyFunc != nil {
|
||||
proxy, err := proxyFunc(&http.Request{URL: &url.URL{Scheme: "https", Host: target}})
|
||||
if err == nil && proxy != nil {
|
||||
conn, err := dialer.DialContext(ctx, "tcp", proxy.Host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// CONNECT tunnel
|
||||
fmt.Fprintf(conn, "CONNECT %s HTTP/1.1\r\nHost: %s\r\n\r\n", target, target)
|
||||
br := bufio.NewReader(conn)
|
||||
resp, err := http.ReadResponse(br, nil)
|
||||
if err != nil || resp.StatusCode != 200 {
|
||||
conn.Close()
|
||||
return nil, fmt.Errorf("proxy CONNECT failed: %v", err)
|
||||
}
|
||||
host, _, _ := net.SplitHostPort(target)
|
||||
uconn := utls.UClient(conn, &utls.Config{
|
||||
ServerName: host,
|
||||
InsecureSkipVerify: insecureSkipVerify,
|
||||
MinVersion: tls.VersionTLS12,
|
||||
}, utls.HelloFirefox_120)
|
||||
if err := uconn.HandshakeContext(ctx); err != nil {
|
||||
conn.Close()
|
||||
return nil, err
|
||||
}
|
||||
return uconn, nil
|
||||
}
|
||||
}
|
||||
// Прямое соединение (без прокси)
|
||||
conn, err := dialer.DialContext(ctx, network, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
host, _, _ := net.SplitHostPort(addr)
|
||||
uconn := utls.UClient(conn, &utls.Config{
|
||||
ServerName: host,
|
||||
InsecureSkipVerify: insecureSkipVerify,
|
||||
MinVersion: tls.VersionTLS12,
|
||||
}, utls.HelloFirefox_120)
|
||||
if err := uconn.HandshakeContext(ctx); err != nil {
|
||||
conn.Close()
|
||||
return nil, err
|
||||
}
|
||||
return uconn, nil
|
||||
// Отключаем HTTP/2: ColdFusion + DDoS-Guard не поддерживают h2 → EOF.
|
||||
// Пустой TLSNextProto убирает h2 из ALPN → только HTTP/1.1.
|
||||
transport.TLSNextProto = make(map[string]func(authority string, c *tls.Conn) http.RoundTripper)
|
||||
transport.TLSClientConfig = &tls.Config{
|
||||
InsecureSkipVerify: insecureSkipVerify,
|
||||
MinVersion: tls.VersionTLS12,
|
||||
}
|
||||
|
||||
// Определяем уровень логирования операций: none (тихий) / info / debug.
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
version string = "5.0.66"
|
||||
version string = "5.0.68"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
Reference in New Issue
Block a user