Skip to content

Commit

Permalink
refine unguarded
Browse files Browse the repository at this point in the history
Signed-off-by: iosmanthus <myosmanthustree@gmail.com>
  • Loading branch information
iosmanthus committed Jun 7, 2024
1 parent 84a17a1 commit 98df57e
Show file tree
Hide file tree
Showing 4 changed files with 162 additions and 38 deletions.
2 changes: 1 addition & 1 deletion nixos/gcp-instance-0/subgen/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ let
server_name = config.sops.placeholder."sing-box/shadowtls/handshake/server";
utls = {
enabled = true;
fingerprint = "chrome";
fingerprint = "safari";
};
};
};
Expand Down
110 changes: 99 additions & 11 deletions packages/unguarded/dlercloud/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,36 +8,57 @@ import (
"net/http/cookiejar"
"net/url"
"strconv"
"strings"
"time"

"github.com/PuerkitoBio/goquery"
)

var _ Client = (*client)(nil)

const (
relayPath = "user/cusrelay"
relayPath = "user/cusrelay"
relayCreatePath = "user/cusrelay/create"
)

type Relay struct {
SourceName string `json:"source_name"`
SourceNode string `json:"source_node"`
SourceHost string `json:"source_host"`
SourcePort int `json:"source_port"`

TargetHost string `json:"target_host"`
TargetPort int `json:"target_port"`
}

type CreateRelay struct {
SourceNode string `json:"source_node" form:"source_node"`
TargetHost string `json:"target_host" form:"target_host"`
TargetPort string `json:"target_port" form:"target_port"`
}

type SourceNode struct {
Name string `json:"name"`
ID string `json:"id"`
}

type Auth struct {
UID string `json:"uid"`
Email string `json:"email"`
Key string `json:"key"`
UID string `json:"uid" form:"uid"`
Email string `json:"email" form:"email"`
Key string `json:"key" form:"key"`
}

type Client interface {
ListRelays(ctx context.Context) ([]*Relay, error)
ListSourceNodes(ctx context.Context) ([]*SourceNode, error)
CreateRelay(ctx context.Context, request *CreateRelay) error
}

type Client struct {
type client struct {
endpoint string
inner *http.Client
}

func NewClient(endpoint string, auth Auth) (*Client, error) {
func NewClient(endpoint string, auth Auth) (Client, error) {
u, err := url.Parse(endpoint)
if err != nil {
return nil, err
Expand All @@ -60,13 +81,13 @@ func NewClient(endpoint string, auth Auth) (*Client, error) {
Jar: jar,
}

return &Client{
return &client{
endpoint: endpoint,
inner: inner,
}, nil
}

func (c *Client) List(ctx context.Context) ([]*Relay, error) {
func (c *client) ListRelays(ctx context.Context) ([]*Relay, error) {
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/%s", c.endpoint, relayPath), nil)
if err != nil {
return nil, err
Expand All @@ -92,7 +113,7 @@ func parseHTMLRelayTable(reader io.Reader) ([]*Relay, error) {
}

var relays []*Relay
doc.Find("table").Find("tr").EachWithBreak(func(i int, s *goquery.Selection) bool {
doc.Find("#rule_table tr").EachWithBreak(func(i int, s *goquery.Selection) bool {
if len(s.ChildrenFiltered("td").Nodes) == 0 {
return true
}
Expand All @@ -112,7 +133,7 @@ func parseHTMLRelayTable(reader io.Reader) ([]*Relay, error) {
}

relays = append(relays, &Relay{
SourceName: s.ChildrenFiltered("td:nth-child(3)").Text(),
SourceNode: s.ChildrenFiltered("td:nth-child(3)").Text(),
SourceHost: s.ChildrenFiltered("td:nth-child(4)").Text(),
TargetHost: s.ChildrenFiltered("td:nth-child(6)").Text(),

Expand All @@ -125,3 +146,70 @@ func parseHTMLRelayTable(reader io.Reader) ([]*Relay, error) {

return relays, nil
}

func (c *client) ListSourceNodes(ctx context.Context) ([]*SourceNode, error) {
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/%s", c.endpoint, relayCreatePath), nil)
if err != nil {
return nil, err
}

resp, err := c.inner.Do(req.WithContext(ctx))
if err != nil {
return nil, err
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("fail to list source nodes: status %s", resp.Status)
}

return parseHTMLNodes(resp.Body)
}

func parseHTMLNodes(reader io.Reader) ([]*SourceNode, error) {
doc, err := goquery.NewDocumentFromReader(reader)
if err != nil {
return nil, err
}

var nodes []*SourceNode
doc.Find("#source_node option").Each(func(i int, s *goquery.Selection) {
value := s.AttrOr("value", "0")
if value == "0" {
return
}

nodes = append(nodes, &SourceNode{
Name: s.Text(),
ID: value,
})
})

return nodes, nil
}

func (c *client) CreateRelay(ctx context.Context, request *CreateRelay) error {
data := url.Values{}
data.Set("source_node", request.SourceNode)
data.Set("dist_add", request.TargetHost)
data.Set("port", request.TargetPort)
data.Set("relay_mode", "0")

req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s/%s", c.endpoint, relayPath), strings.NewReader(data.Encode()))
if err != nil {
return err
}

req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

resp, err := c.inner.Do(req.WithContext(ctx))
if err != nil {
return err
}

if resp.StatusCode != http.StatusOK {
return fmt.Errorf("fail to create relay: status %s", resp.Status)
}

return nil
}
78 changes: 57 additions & 21 deletions packages/unguarded/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package main

import (
"flag"
"fmt"
"log"
"net/http"

"github.com/iosmanthus/nixos-config/packages/unguarded/dlercloud"

Expand All @@ -20,35 +20,71 @@ func main() {

r := gin.Default()
r.GET("/dlercloud/v1/relay/list", func(c *gin.Context) {
params := []string{"uid", "email", "key"}
queries := make([]string, len(params))
for i, p := range params {
q, ok := c.GetQuery(p)
if !ok {
c.JSON(400, gin.H{"error": fmt.Sprintf("missing parameter: `%s`", p)})
return
}
queries[i] = q
}

dcli, err := dlercloud.NewClient(*dlercloudEndpoint, dlercloud.Auth{
UID: queries[0],
Email: queries[1],
Key: queries[2],
})
var auth dlercloud.Auth
if c.BindQuery(&auth) != nil {
return
}

dcli, err := dlercloud.NewClient(*dlercloudEndpoint, auth)
if err != nil {
_ = c.AbortWithError(http.StatusInternalServerError, err)
return
}

relays, err := dcli.ListRelays(c)
if err != nil {
_ = c.AbortWithError(http.StatusInternalServerError, err)
return
}

c.JSON(http.StatusOK, gin.H{"relays": relays})
})

r.GET("/dlercloud/v1/relay/source_node/list", func(c *gin.Context) {
var auth dlercloud.Auth
if c.BindQuery(&auth) != nil {
return
}

dcli, err := dlercloud.NewClient(*dlercloudEndpoint, auth)
if err != nil {
_ = c.AbortWithError(http.StatusInternalServerError, err)
return
}

nodes, err := dcli.ListSourceNodes(c)
if err != nil {
_ = c.AbortWithError(http.StatusInternalServerError, err)
return
}

c.JSON(http.StatusOK, gin.H{"source_nodes": nodes})
})

r.POST("/dlercloud/v1/relay/create", func(c *gin.Context) {
var auth dlercloud.Auth
if c.BindQuery(&auth) != nil {
return
}

var createRelay dlercloud.CreateRelay
if c.BindJSON(&createRelay) != nil {
return
}

dcli, err := dlercloud.NewClient(*dlercloudEndpoint, auth)
if err != nil {
c.JSON(500, gin.H{"error": err.Error()})
_ = c.AbortWithError(http.StatusInternalServerError, err)
return
}

relays, err := dcli.List(c)
err = dcli.CreateRelay(c, &createRelay)
if err != nil {
c.JSON(500, gin.H{"error": err.Error()})
_ = c.AbortWithError(http.StatusInternalServerError, err)
return
}

c.JSON(200, gin.H{"relays": relays})
c.Status(http.StatusOK)
})

err := r.Run(*addr)
Expand Down
Loading

0 comments on commit 98df57e

Please sign in to comment.