mirror of
https://github.com/MengMengCode/VoCat.git
synced 2026-08-22 07:43:43 +08:00
feat: expand device networking and management
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
package exportproxy
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func serveHTTP(client net.Conn, config Config, dialer *net.Dialer, resolver *net.Resolver) error {
|
||||
reader := bufio.NewReader(client)
|
||||
request, err := http.ReadRequest(reader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if config.AuthEnabled && !httpAuthorized(request, config) {
|
||||
_, _ = client.Write([]byte("HTTP/1.1 407 Proxy Authentication Required\r\nProxy-Authenticate: Basic realm=\"vocat-export-proxy\"\r\n\r\n"))
|
||||
return errors.New("HTTP proxy authentication required")
|
||||
}
|
||||
if request.Method == http.MethodConnect {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), proxyTimeout)
|
||||
target, err := dialTarget(ctx, request.URL.Host, dialer, resolver)
|
||||
cancel()
|
||||
if err != nil {
|
||||
_, _ = fmt.Fprint(client, "HTTP/1.1 502 Bad Gateway\r\n\r\n")
|
||||
return err
|
||||
}
|
||||
defer target.Close()
|
||||
if _, err := client.Write([]byte("HTTP/1.1 200 Connection Established\r\n\r\n")); err != nil {
|
||||
return err
|
||||
}
|
||||
if buffered := reader.Buffered(); buffered > 0 {
|
||||
if value, err := reader.Peek(buffered); err == nil {
|
||||
_, _ = target.Write(value)
|
||||
_, _ = reader.Discard(buffered)
|
||||
}
|
||||
}
|
||||
pipe(client, target)
|
||||
return nil
|
||||
}
|
||||
|
||||
request.Header.Del("Proxy-Authorization")
|
||||
request.Header.Del("Proxy-Connection")
|
||||
request.RequestURI = ""
|
||||
transport := &http.Transport{
|
||||
DialContext: func(ctx context.Context, _, address string) (net.Conn, error) {
|
||||
return dialTarget(ctx, address, dialer, resolver)
|
||||
},
|
||||
DisableKeepAlives: true,
|
||||
}
|
||||
response, err := transport.RoundTrip(request)
|
||||
if err != nil {
|
||||
_, _ = fmt.Fprint(client, "HTTP/1.1 502 Bad Gateway\r\n\r\n")
|
||||
return err
|
||||
}
|
||||
defer response.Body.Close()
|
||||
return response.Write(client)
|
||||
}
|
||||
|
||||
func httpAuthorized(request *http.Request, config Config) bool {
|
||||
header := strings.TrimSpace(strings.TrimPrefix(request.Header.Get("Proxy-Authorization"), "Basic "))
|
||||
decoded, err := base64.StdEncoding.DecodeString(header)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
parts := strings.SplitN(string(decoded), ":", 2)
|
||||
return len(parts) == 2 && parts[0] == config.Username && parts[1] == config.Password
|
||||
}
|
||||
Reference in New Issue
Block a user