mirror of
https://github.com/phishingclub/phishingclub.git
synced 2026-02-12 16:12:44 +00:00
add support for proxy socks5
Signed-off-by: Ronni Skansing <rskansing@gmail.com>
This commit is contained in:
@@ -9,6 +9,7 @@ import (
|
||||
|
||||
"github.com/enetx/surf"
|
||||
"github.com/phishingclub/phishingclub/service"
|
||||
"golang.org/x/net/proxy"
|
||||
)
|
||||
|
||||
// browserProfile represents detected browser and platform information
|
||||
@@ -133,9 +134,13 @@ func (m *ProxyHandler) createSurfClient(userAgent string, proxyConfig *service.P
|
||||
|
||||
// configure proxy if specified
|
||||
if proxyConfig.Proxy != "" {
|
||||
builder = builder.Proxy("http://" + proxyConfig.Proxy)
|
||||
proxyURL, err := m.parseProxyURL(proxyConfig.Proxy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
builder = builder.Proxy(proxyURL.String())
|
||||
m.logger.Debugw("configured surf client with proxy",
|
||||
"proxy", proxyConfig.Proxy,
|
||||
"proxy", proxyURL.String(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -179,6 +184,29 @@ func (m *ProxyHandler) createHTTPClientWithImpersonation(req *http.Request, reqC
|
||||
return client, nil
|
||||
}
|
||||
|
||||
// parseProxyURL parses and normalizes the proxy URL string
|
||||
// if the proxy string is just an IP:port, it prepends "http://"
|
||||
// otherwise it uses the full string to support socks4/socks5 and authentication
|
||||
func (m *ProxyHandler) parseProxyURL(proxyStr string) (*url.URL, error) {
|
||||
// check if the string already contains a scheme (http://, https://, socks4://, socks5://)
|
||||
hasScheme := strings.Contains(proxyStr, "://")
|
||||
|
||||
// check if it contains authentication credentials
|
||||
hasAuth := strings.Contains(proxyStr, "@")
|
||||
|
||||
// if it has a scheme or auth, use it as-is
|
||||
if hasScheme || hasAuth {
|
||||
// if it has auth but no scheme, default to http://
|
||||
if hasAuth && !hasScheme {
|
||||
proxyStr = "http://" + proxyStr
|
||||
}
|
||||
return url.Parse(proxyStr)
|
||||
}
|
||||
|
||||
// otherwise, it's just an IP:port, so prepend http://
|
||||
return url.Parse("http://" + proxyStr)
|
||||
}
|
||||
|
||||
// createStandardHTTPClient creates a standard http client without impersonation
|
||||
func (m *ProxyHandler) createStandardHTTPClient(proxyConfig *service.ProxyServiceConfigYAML) (*http.Client, error) {
|
||||
client := &http.Client{
|
||||
@@ -187,15 +215,42 @@ func (m *ProxyHandler) createStandardHTTPClient(proxyConfig *service.ProxyServic
|
||||
}
|
||||
|
||||
if proxyConfig.Proxy != "" {
|
||||
proxyURL, err := url.Parse("http://" + proxyConfig.Proxy)
|
||||
proxyURL, err := m.parseProxyURL(proxyConfig.Proxy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client.Transport = &http.Transport{
|
||||
Proxy: http.ProxyURL(proxyURL),
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
},
|
||||
|
||||
// handle socks5 proxies
|
||||
if proxyURL.Scheme == "socks5" {
|
||||
var auth *proxy.Auth
|
||||
if proxyURL.User != nil {
|
||||
password, _ := proxyURL.User.Password()
|
||||
auth = &proxy.Auth{
|
||||
User: proxyURL.User.Username(),
|
||||
Password: password,
|
||||
}
|
||||
}
|
||||
|
||||
// create socks5 dialer
|
||||
dialer, err := proxy.SOCKS5("tcp", proxyURL.Host, auth, proxy.Direct)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client.Transport = &http.Transport{
|
||||
Dial: dialer.Dial,
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
},
|
||||
}
|
||||
} else {
|
||||
// handle http/https proxies
|
||||
client.Transport = &http.Transport{
|
||||
Proxy: http.ProxyURL(proxyURL),
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
return client, nil
|
||||
|
||||
@@ -1408,6 +1408,11 @@ func (m *Proxy) validateProxyConfig(ctx context.Context, proxy *model.Proxy) err
|
||||
return validate.WrapErrorWithField(err, "proxyConfig")
|
||||
}
|
||||
|
||||
// validate forward proxy configuration
|
||||
if err := m.validateForwardProxy(&config); err != nil {
|
||||
return validate.WrapErrorWithField(err, "proxyConfig")
|
||||
}
|
||||
|
||||
// validate that at least one domain mapping exists
|
||||
if len(config.Hosts) == 0 {
|
||||
return validate.WrapErrorWithField(errors.New("at least one domain mapping must be specified"), "proxyConfig")
|
||||
@@ -1583,6 +1588,34 @@ func (m *Proxy) validateProxyConfig(ctx context.Context, proxy *model.Proxy) err
|
||||
return nil
|
||||
}
|
||||
|
||||
// validateForwardProxy validates the forward proxy configuration
|
||||
func (m *Proxy) validateForwardProxy(config *ProxyServiceConfigYAML) error {
|
||||
if config.Proxy == "" {
|
||||
return nil // proxy is optional
|
||||
}
|
||||
|
||||
// check if it contains socks4 scheme
|
||||
if strings.HasPrefix(config.Proxy, "socks4://") {
|
||||
return errors.New("socks4 proxies are not supported. please use socks5:// instead")
|
||||
}
|
||||
|
||||
// validate that it can be parsed as a URL if it has a scheme
|
||||
if strings.Contains(config.Proxy, "://") {
|
||||
parsedURL, err := url.Parse(config.Proxy)
|
||||
if err != nil {
|
||||
return errors.New("invalid proxy URL format: " + err.Error())
|
||||
}
|
||||
|
||||
// validate supported schemes
|
||||
scheme := parsedURL.Scheme
|
||||
if scheme != "http" && scheme != "https" && scheme != "socks5" {
|
||||
return errors.New(fmt.Sprintf("unsupported proxy scheme '%s'. supported schemes: http, https, socks5", scheme))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// validateGlobalCaptureNameUniqueness ensures all capture rule names are unique across the entire Proxy configuration
|
||||
func (m *Proxy) validateGlobalCaptureNameUniqueness(config *ProxyServiceConfigYAML) error {
|
||||
allCaptureNames := make(map[string]string) // name -> location
|
||||
|
||||
@@ -67,7 +67,15 @@
|
||||
let isLoadingIPAllowList = false;
|
||||
|
||||
const currentExample = `version: "0.0"
|
||||
proxy: "My Proxy Campaign"
|
||||
|
||||
# optional: forward proxy for outbound requests
|
||||
# if just ip:port is provided, http:// is automatically prepended
|
||||
# supported formats:
|
||||
# proxy: "192.168.1.100:8080" # http proxy (ip:port)
|
||||
# proxy: "http://192.168.1.100:8080" # http proxy with scheme
|
||||
# proxy: "socks5://192.168.1.100:1080" # socks5 proxy
|
||||
# proxy: "socks5://user:pass@192.168.1.100:1080" # socks5 with auth
|
||||
# proxy: "http://user:pass@192.168.1.100:8080" # http with auth
|
||||
|
||||
# global TLS configuration (applies to all hosts unless overridden)
|
||||
global:
|
||||
|
||||
Reference in New Issue
Block a user