Files
x_gift_bot/internal/proxy/proxy.go
T
mizorewww a8e7565448 fix(proxy): ignore services, endpoints and experimental sections
A pasted sing-box config carrying services (api/ssm-api), endpoints
(wireguard/tailscale), or experimental controllers (clash/v2ray/debug)
could bind non-loopback listeners or alter host networking once the
full include registries are enabled. Strip those sections so the
proxy record can only forward traffic; outbounds, route and dns still
pass through. Align the README outbound list (dns outbound was
removed in sing-box 1.12) and document the stripped sections.
2026-10-03 12:09:37 +08:00

69 lines
2.2 KiB
Go

package proxy
import (
"context"
stdjson "encoding/json"
"fmt"
"net/http"
"net/url"
"os"
"time"
box "github.com/sagernet/sing-box"
"github.com/sagernet/sing-box/include"
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing/common/json"
)
func Start(ctx context.Context, config []byte, port int) (*box.Box, error) {
ctx = include.Context(ctx)
var raw map[string]any
if err := stdjson.Unmarshal(config, &raw); err != nil {
return nil, fmt.Errorf("invalid proxy configuration")
}
outbounds, ok := raw["outbounds"].([]any)
if !ok || len(outbounds) == 0 {
return nil, fmt.Errorf("proxy configuration must contain at least one outbound")
}
// Only traffic forwarding is allowed: drop every section that could
// open listeners or alter the host (API services, TUN endpoints,
// clash/v2ray/debug controllers). Outbounds, route and dns pass through.
delete(raw, "services")
delete(raw, "endpoints")
delete(raw, "experimental")
raw["log"] = map[string]any{"disabled": true}
raw["inbounds"] = []any{map[string]any{"type": "mixed", "listen": "127.0.0.1", "listen_port": port}}
data, err := stdjson.Marshal(raw)
if err != nil {
return nil, err
}
opts, err := json.UnmarshalExtendedContext[option.Options](ctx, data)
if err != nil {
return nil, fmt.Errorf("invalid embedded sing-box options")
}
instance, err := box.New(box.Options{Context: ctx, Options: opts})
if err != nil {
return nil, fmt.Errorf("initialize embedded sing-box: %w", err)
}
if err = instance.Start(); err != nil {
instance.Close()
return nil, fmt.Errorf("start embedded sing-box: %w", err)
}
return instance, nil
}
func Check(ctx context.Context, port int) error {
p, _ := url.Parse(fmt.Sprintf("http://127.0.0.1:%d", port))
tr := &http.Transport{Proxy: http.ProxyURL(p), TLSHandshakeTimeout: 15 * time.Second}
defer tr.CloseIdleConnections()
client := &http.Client{Transport: tr, Timeout: 25 * time.Second}
req, _ := http.NewRequestWithContext(ctx, "HEAD", "https://x.com", nil)
res, err := client.Do(req)
if err != nil {
return fmt.Errorf("local proxy is running, but HTTPS to X failed: %w", err)
}
defer res.Body.Close()
fmt.Fprintf(os.Stderr, "X HTTPS reachable, HTTP status %d\n", res.StatusCode)
return nil
}