-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
388 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
package cli | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"strings" | ||
) | ||
|
||
func Run(args []string) error { | ||
if len(args) == 0 { | ||
return errors.New("no arguments provided. Use --help for usage") | ||
} | ||
|
||
switch args[0] { | ||
case "-V", "--version": | ||
fmt.Println("WebProxy CLI version 1.0.0") | ||
case "-h", "--help": | ||
printHelp() | ||
default: | ||
// 调用子命令 | ||
return executeCommand(args) | ||
} | ||
return nil | ||
} | ||
|
||
func printHelp() { | ||
fmt.Println(`WebProxy CLI | ||
Commands: | ||
proxy Run the proxy server | ||
--server_port 设置监听端口(必须,否则无法启动) | ||
--proxy_port 设置代理端口(必须,否则无法启动) | ||
--proxy_ip 设置代理ip(非必须,默认为127.0.0.1) | ||
--log_mode 设置日志模式默认 cli(仅仅控制台打印) save(保存到指定路径文件) | ||
--log_path 设置日志文件路径(如果log_mode为save则必须要填,反之则一定不要填写) | ||
--waf_rules 设置waf规则文件路径(非必须,不填写则不启动waf功能) | ||
-V, --version Show the CLI version | ||
-h, --help Show this help message`) | ||
} | ||
|
||
func executeCommand(args []string) error { | ||
command := args[0] | ||
parsedArgs := parseArgs(args[1:]) | ||
|
||
switch command { | ||
case "proxy": | ||
return runProxy(parsedArgs) | ||
default: | ||
return fmt.Errorf("unknown command: %s. Use --help for usage", command) | ||
} | ||
} | ||
|
||
// parseArgs 将参数解析为键值对 | ||
func parseArgs(args []string) map[string]string { | ||
parsed := make(map[string]string) | ||
for i := 0; i < len(args); i++ { | ||
arg := args[i] | ||
if strings.HasPrefix(arg, "--") { | ||
key := strings.TrimPrefix(arg, "--") | ||
// 检查是否有下一个值,并且下一个值不是另一个选项 | ||
if i+1 < len(args) && !strings.HasPrefix(args[i+1], "--") { | ||
parsed[key] = args[i+1] | ||
i++ | ||
} else { | ||
parsed[key] = "" // 没有值的选项 | ||
} | ||
} else { | ||
// 非选项参数,按顺序存储 | ||
parsed[arg] = "" | ||
} | ||
} | ||
return parsed | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
package cli | ||
|
||
import ( | ||
"bytes" | ||
"encoding/json" | ||
"fmt" | ||
"io" | ||
"net/http" | ||
"net/url" | ||
"os" | ||
"time" | ||
) | ||
|
||
// LogEntry 定义日志结构 | ||
type LogEntry struct { | ||
Timestamp string `json:"timestamp"` | ||
Method string `json:"method"` | ||
URL string `json:"url"` | ||
Headers map[string]string `json:"headers"` | ||
Body string `json:"body,omitempty"` | ||
} | ||
|
||
func runProxy(args map[string]string) error { | ||
// 获取 server_port 和 proxy_port 参数 | ||
serverPort := args["server_port"] | ||
if serverPort == "" { | ||
fmt.Println("server_port is required, server failed to start") | ||
return nil | ||
} | ||
|
||
proxyPort := args["proxy_port"] | ||
if proxyPort == "" { | ||
fmt.Println("proxy_port is required, proxy failed to start") | ||
return nil | ||
} | ||
|
||
proxyIP := args["proxy_ip"] | ||
if proxyIP == "" { | ||
proxyIP = "127.0.0.1" // 默认代理 IP | ||
} | ||
rulesFile := args["waf_rules"] // 获取 WAF 规则文件路径 | ||
|
||
// 获取 log_mode 和 log_path 参数 | ||
logMode := args["log_mode"] | ||
logPath := args["log_path"] | ||
if logMode == "" { | ||
logMode = "cli" | ||
} | ||
// 启动代理服务器 | ||
fmt.Printf("Starting HTTP proxy server on port %s, forwarding to %s:%s...\n", serverPort, proxyIP, proxyPort) | ||
return server(serverPort, proxyIP, proxyPort, logMode, logPath, rulesFile) | ||
} | ||
|
||
func server(serverPort, proxyIP, proxyPort, logMode, logPath, rulesFile string) error { | ||
// 构造目标地址 | ||
proxyURL := fmt.Sprintf("http://%s:%s", proxyIP, proxyPort) | ||
targetURL, err := url.Parse(proxyURL) | ||
if err != nil { | ||
return fmt.Errorf("failed to parse proxy URL: %v", err) | ||
} | ||
|
||
// 创建日志处理器 | ||
var logWriter io.Writer | ||
if logMode == "cli" { | ||
logWriter = os.Stdout | ||
} else if logMode == "save" { | ||
if logPath == "" { | ||
return fmt.Errorf("log_path is required in 'save' mode") | ||
} | ||
logFile, err := os.OpenFile(logPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) | ||
if err != nil { | ||
return fmt.Errorf("failed to open log file: %v", err) | ||
} | ||
defer logFile.Close() | ||
logWriter = logFile | ||
} else { | ||
logWriter = nil // 不记录日志 | ||
} | ||
|
||
// 创建反向代理处理器 | ||
proxy := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
// 如果指定了 WAF 规则文件,进行 WAF 检查 | ||
if rulesFile != "" { | ||
if err := waf(r, rulesFile); err != nil { | ||
http.Error(w, fmt.Sprintf("WAF validation failed: %v", err), http.StatusForbidden) | ||
return | ||
} | ||
} | ||
|
||
// 记录请求头 | ||
headers := make(map[string]string) | ||
for key, values := range r.Header { | ||
headers[key] = values[0] | ||
} | ||
|
||
// 保存请求体(用于 POST/PUT 等方法记录 data) | ||
var bodyData string | ||
if r.Method == http.MethodPost || r.Method == http.MethodPut || r.Method == http.MethodPatch { | ||
bodyBytes, err := io.ReadAll(r.Body) | ||
if err == nil { | ||
bodyData = string(bodyBytes) | ||
r.Body = io.NopCloser(bytes.NewReader(bodyBytes)) // 恢复请求体供后续使用 | ||
} else { | ||
bodyData = fmt.Sprintf("failed to read body: %v", err) | ||
} | ||
} | ||
|
||
// 构造日志条目 | ||
logEntry := LogEntry{ | ||
Timestamp: time.Now().Format(time.RFC3339), | ||
Method: r.Method, | ||
URL: r.URL.String(), | ||
Headers: headers, | ||
Body: bodyData, | ||
} | ||
|
||
// 输出日志 | ||
if logWriter != nil { | ||
logData, err := json.Marshal(logEntry) | ||
if err == nil { | ||
logData = append(logData, '\n') // 每行一个 JSON 对象 | ||
_, _ = logWriter.Write(logData) | ||
} | ||
} | ||
|
||
// 转发请求到目标服务器 | ||
r.URL.Scheme = targetURL.Scheme | ||
r.URL.Host = targetURL.Host | ||
r.Host = targetURL.Host | ||
|
||
resp, err := http.DefaultTransport.RoundTrip(r) | ||
if err != nil { | ||
http.Error(w, fmt.Sprintf("proxy error: %v", err), http.StatusBadGateway) | ||
return | ||
} | ||
defer resp.Body.Close() | ||
|
||
// 将目标服务器的响应写回客户端 | ||
for key, values := range resp.Header { | ||
for _, value := range values { | ||
w.Header().Add(key, value) | ||
} | ||
} | ||
w.WriteHeader(resp.StatusCode) | ||
io.Copy(w, resp.Body) | ||
}) | ||
|
||
// 启动 HTTP 服务器 | ||
serverAddr := fmt.Sprintf(":%s", serverPort) | ||
fmt.Printf("Proxy server is running at %s\n", serverAddr) | ||
return http.ListenAndServe(serverAddr, proxy) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
package cli | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"gopkg.in/yaml.v3" | ||
"io" | ||
"net/http" | ||
"os" | ||
"regexp" | ||
) | ||
|
||
// WAFRules 定义 WAF 规则结构 | ||
type WAFRules struct { | ||
Low WAFRuleSet `yaml:"low"` | ||
High WAFRuleSet `yaml:"high"` | ||
} | ||
|
||
// WAFRuleSet 定义单个规则集 | ||
type WAFRuleSet struct { | ||
Allow WAFRule `yaml:"allow"` | ||
Disallow WAFRule `yaml:"disallow"` | ||
} | ||
|
||
// WAFRule 定义规则内容 | ||
type WAFRule struct { | ||
Agent []string `yaml:"agent"` | ||
Body []string `yaml:"body"` | ||
URL []string `yaml:"url"` | ||
} | ||
|
||
// waf 函数加载规则并检查请求 | ||
func waf(r *http.Request, rulesFile string) error { | ||
// 加载规则文件 | ||
data, err := os.ReadFile(rulesFile) | ||
if err != nil { | ||
return fmt.Errorf("failed to read rules file: %v", err) | ||
} | ||
|
||
// 解析 YAML 文件 | ||
var wafRules WAFRules | ||
if err := yaml.Unmarshal(data, &wafRules); err != nil { | ||
return fmt.Errorf("failed to parse rules file: %v", err) | ||
} | ||
|
||
// 1. 检查 URL | ||
urlPath := r.URL.Path | ||
if err := checkRuleWithHigh(urlPath, wafRules.Low.Allow.URL, wafRules.Low.Disallow.URL, wafRules.High.Allow.URL); err != nil { | ||
return err | ||
} | ||
|
||
// 2. 检查 User-Agent | ||
userAgent := r.Header.Get("User-Agent") | ||
if err := checkRuleWithHigh(userAgent, wafRules.Low.Allow.Agent, wafRules.Low.Disallow.Agent, wafRules.High.Allow.Agent); err != nil { | ||
return err | ||
} | ||
|
||
// 3. 检查 Body 内容 | ||
var bodyData string | ||
if r.Body != nil { | ||
bodyBytes, _ := io.ReadAll(r.Body) | ||
bodyData = string(bodyBytes) | ||
r.Body = io.NopCloser(bytes.NewReader(bodyBytes)) | ||
} | ||
if err := checkRuleWithHigh(bodyData, wafRules.Low.Allow.Body, wafRules.Low.Disallow.Body, wafRules.High.Allow.Body); err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// checkRuleWithHigh 检查规则,并考虑 high 规则的覆盖 | ||
func checkRuleWithHigh(content string, allowRules []string, disallowRules []string, highAllowRules []string) error { | ||
// 如果禁止规则匹配,直接返回错误 | ||
for _, rule := range disallowRules { | ||
if match, _ := regexp.MatchString(rule, content); match { | ||
// 如果 low 规则拒绝了,但 high 规则允许某些内容,继续检查 high 规则 | ||
for _, highAllowRule := range highAllowRules { | ||
if match, _ := regexp.MatchString(highAllowRule, content); match { | ||
// 如果 high 规则允许更大的词语,放行请求 | ||
return nil | ||
} | ||
} | ||
return fmt.Errorf("content matches disallowed rule: %s", rule) | ||
} | ||
} | ||
|
||
// 如果允许规则不为空且未匹配,返回错误 | ||
if len(allowRules) > 0 { | ||
matched := false | ||
for _, rule := range allowRules { | ||
if match, _ := regexp.MatchString(rule, content); match { | ||
matched = true | ||
break | ||
} | ||
} | ||
if !matched { | ||
return fmt.Errorf("content does not match any allowed rules") | ||
} | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
module webproxy | ||
|
||
go 1.23 | ||
|
||
require gopkg.in/yaml.v3 v3.0.1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | ||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{"timestamp":"2025-01-04T14:52:12+08:00","method":"GET","url":"/api/allowed","headers":{"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7","Accept-Encoding":"gzip, deflate, br, zstd","Accept-Language":"zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7","Cache-Control":"max-age=0","Connection":"keep-alive","Cookie":"authToken=b504a6c8db6b4861","Sec-Ch-Ua":"\"Google Chrome\";v=\"131\", \"Chromium\";v=\"131\", \"Not_A Brand\";v=\"24\"","Sec-Ch-Ua-Mobile":"?0","Sec-Ch-Ua-Platform":"\"Windows\"","Sec-Fetch-Dest":"document","Sec-Fetch-Mode":"navigate","Sec-Fetch-Site":"none","Sec-Fetch-User":"?1","Upgrade-Insecure-Requests":"1","User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"}} | ||
{"timestamp":"2025-01-04T15:07:04+08:00","method":"POST","url":"/console/machines","headers":{"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7","Accept-Encoding":"gzip, deflate, br, zstd","Accept-Language":"zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7","Cache-Control":"max-age=0","Connection":"keep-alive","Content-Length":"9","Content-Type":"application/x-www-form-urlencoded","Cookie":"authToken=b504a6c8db6b4861","Origin":"http://127.0.0.1:8080","Referer":"http://127.0.0.1:8080/api/allowed","Sec-Ch-Ua":"\"Google Chrome\";v=\"131\", \"Chromium\";v=\"131\", \"Not_A Brand\";v=\"24\"","Sec-Ch-Ua-Mobile":"?0","Sec-Ch-Ua-Platform":"\"Windows\"","Sec-Fetch-Dest":"document","Sec-Fetch-Mode":"navigate","Sec-Fetch-Site":"none","Sec-Fetch-User":"?1","Upgrade-Insecure-Requests":"1","User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"},"body":"data=data"} | ||
{"timestamp":"2025-01-04T15:07:55+08:00","method":"POST","url":"/console/machines","headers":{"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7","Accept-Encoding":"gzip, deflate, br, zstd","Accept-Language":"zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7","Cache-Control":"max-age=0","Connection":"keep-alive","Content-Length":"14","Content-Type":"application/x-www-form-urlencoded","Cookie":"authToken=b504a6c8db6b4861","Origin":"http://127.0.0.1:8080","Referer":"http://127.0.0.1:8080/console/machines","Sec-Ch-Ua":"\"Google Chrome\";v=\"131\", \"Chromium\";v=\"131\", \"Not_A Brand\";v=\"24\"","Sec-Ch-Ua-Mobile":"?0","Sec-Ch-Ua-Platform":"\"Windows\"","Sec-Fetch-Dest":"document","Sec-Fetch-Mode":"navigate","Sec-Fetch-Site":"none","Sec-Fetch-User":"?1","Upgrade-Insecure-Requests":"1","User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"},"body":"testhight=data"} | ||
{"timestamp":"2025-01-04T15:08:24+08:00","method":"POST","url":"/console/machines","headers":{"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7","Accept-Encoding":"gzip, deflate, br, zstd","Accept-Language":"zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7","Cache-Control":"max-age=0","Connection":"keep-alive","Content-Length":"14","Content-Type":"application/x-www-form-urlencoded","Cookie":"authToken=b504a6c8db6b4861","Origin":"http://127.0.0.1:8080","Referer":"http://127.0.0.1:8080/console/machines","Sec-Ch-Ua":"\"Google Chrome\";v=\"131\", \"Chromium\";v=\"131\", \"Not_A Brand\";v=\"24\"","Sec-Ch-Ua-Mobile":"?0","Sec-Ch-Ua-Platform":"\"Windows\"","Sec-Fetch-Dest":"document","Sec-Fetch-Mode":"navigate","Sec-Fetch-Site":"none","Sec-Fetch-User":"?1","Upgrade-Insecure-Requests":"1","User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"},"body":"testhight=data"} | ||
{"timestamp":"2025-01-04T15:08:58+08:00","method":"GET","url":"/console/machines","headers":{"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7","Accept-Encoding":"gzip, deflate, br, zstd","Accept-Language":"zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7","Cache-Control":"max-age=0","Connection":"keep-alive","Cookie":"authToken=b504a6c8db6b4861","Sec-Ch-Ua":"\"Google Chrome\";v=\"131\", \"Chromium\";v=\"131\", \"Not_A Brand\";v=\"24\"","Sec-Ch-Ua-Mobile":"?0","Sec-Ch-Ua-Platform":"\"Windows\"","Sec-Fetch-Dest":"document","Sec-Fetch-Mode":"navigate","Sec-Fetch-Site":"none","Sec-Fetch-User":"?1","Upgrade-Insecure-Requests":"1","User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"}} | ||
{"timestamp":"2025-01-04T15:08:59+08:00","method":"GET","url":"/console/machines","headers":{"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7","Accept-Encoding":"gzip, deflate, br, zstd","Accept-Language":"zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7","Cache-Control":"max-age=0","Connection":"keep-alive","Cookie":"authToken=b504a6c8db6b4861","Sec-Ch-Ua":"\"Google Chrome\";v=\"131\", \"Chromium\";v=\"131\", \"Not_A Brand\";v=\"24\"","Sec-Ch-Ua-Mobile":"?0","Sec-Ch-Ua-Platform":"\"Windows\"","Sec-Fetch-Dest":"document","Sec-Fetch-Mode":"navigate","Sec-Fetch-Site":"none","Sec-Fetch-User":"?1","Upgrade-Insecure-Requests":"1","User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"}} | ||
{"timestamp":"2025-01-04T15:09:04+08:00","method":"POST","url":"/console/machines","headers":{"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7","Accept-Encoding":"gzip, deflate, br, zstd","Accept-Language":"zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7","Cache-Control":"max-age=0","Connection":"keep-alive","Content-Length":"14","Content-Type":"application/x-www-form-urlencoded","Cookie":"authToken=b504a6c8db6b4861","Origin":"http://127.0.0.1:8080","Referer":"http://127.0.0.1:8080/console/machines","Sec-Ch-Ua":"\"Google Chrome\";v=\"131\", \"Chromium\";v=\"131\", \"Not_A Brand\";v=\"24\"","Sec-Ch-Ua-Mobile":"?0","Sec-Ch-Ua-Platform":"\"Windows\"","Sec-Fetch-Dest":"document","Sec-Fetch-Mode":"navigate","Sec-Fetch-Site":"none","Sec-Fetch-User":"?1","Upgrade-Insecure-Requests":"1","User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"},"body":"testhight=data"} | ||
{"timestamp":"2025-01-04T15:09:17+08:00","method":"POST","url":"/console/machines","headers":{"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7","Accept-Encoding":"gzip, deflate, br, zstd","Accept-Language":"zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7","Cache-Control":"max-age=0","Connection":"keep-alive","Content-Length":"14","Content-Type":"application/x-www-form-urlencoded","Cookie":"authToken=b504a6c8db6b4861","Origin":"http://127.0.0.1:8080","Referer":"http://127.0.0.1:8080/console/machines","Sec-Ch-Ua":"\"Google Chrome\";v=\"131\", \"Chromium\";v=\"131\", \"Not_A Brand\";v=\"24\"","Sec-Ch-Ua-Mobile":"?0","Sec-Ch-Ua-Platform":"\"Windows\"","Sec-Fetch-Dest":"document","Sec-Fetch-Mode":"navigate","Sec-Fetch-Site":"none","Sec-Fetch-User":"?1","Upgrade-Insecure-Requests":"1","User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"},"body":"testhight=data"} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"webproxy/cli" | ||
) | ||
|
||
func main() { | ||
args := os.Args[1:] | ||
if err := cli.Run(args); err != nil { | ||
_, err := fmt.Fprintln(os.Stderr, err) | ||
if err != nil { | ||
return | ||
} | ||
os.Exit(1) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
low: | ||
allow: | ||
agent: | ||
- ".*" | ||
body: | ||
- ".*" | ||
url: | ||
- ".*" | ||
disallow: | ||
agent: | ||
- "curl" | ||
body: | ||
- "test" | ||
- "malicious" | ||
url: | ||
- "/api/restricted" | ||
high: | ||
disallow: | ||
agent: | ||
body: | ||
url: | ||
allow: | ||
agent: | ||
url: | ||
body: | ||
- "testhight" |