mirror of
https://github.com/coaidev/coai.git
synced 2025-05-19 21:10:18 +09:00
feat: support authentication in http/https/socks5 proxies (#126)
This commit is contained in:
parent
3f7e3f9d4b
commit
93c18bb34c
@ -23,6 +23,8 @@ export type Channel = {
|
|||||||
proxy?: {
|
proxy?: {
|
||||||
proxy: string;
|
proxy: string;
|
||||||
proxy_type: number;
|
proxy_type: number;
|
||||||
|
username: string;
|
||||||
|
password: string;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3,6 +3,13 @@ import ChannelTable from "@/components/admin/assemblies/ChannelTable.tsx";
|
|||||||
import ChannelEditor from "@/components/admin/assemblies/ChannelEditor.tsx";
|
import ChannelEditor from "@/components/admin/assemblies/ChannelEditor.tsx";
|
||||||
import { Channel, getChannelInfo } from "@/admin/channel.ts";
|
import { Channel, getChannelInfo } from "@/admin/channel.ts";
|
||||||
|
|
||||||
|
const initialProxyState = {
|
||||||
|
proxy: "",
|
||||||
|
proxy_type: 0,
|
||||||
|
username: "",
|
||||||
|
password: "",
|
||||||
|
};
|
||||||
|
|
||||||
const initialState: Channel = {
|
const initialState: Channel = {
|
||||||
id: -1,
|
id: -1,
|
||||||
type: "openai",
|
type: "openai",
|
||||||
@ -16,10 +23,7 @@ const initialState: Channel = {
|
|||||||
mapper: "",
|
mapper: "",
|
||||||
state: true,
|
state: true,
|
||||||
group: [],
|
group: [],
|
||||||
proxy: {
|
proxy: { ...initialProxyState },
|
||||||
proxy: "",
|
|
||||||
proxy_type: 0,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function reducer(state: Channel, action: any): Channel {
|
function reducer(state: Channel, action: any): Channel {
|
||||||
@ -87,6 +91,8 @@ function reducer(state: Channel, action: any): Channel {
|
|||||||
proxy: {
|
proxy: {
|
||||||
proxy: action.value as string,
|
proxy: action.value as string,
|
||||||
proxy_type: state?.proxy?.proxy_type || 0,
|
proxy_type: state?.proxy?.proxy_type || 0,
|
||||||
|
password: state?.proxy?.password || "",
|
||||||
|
username: state?.proxy?.username || "",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
case "set-proxy-type":
|
case "set-proxy-type":
|
||||||
@ -95,6 +101,28 @@ function reducer(state: Channel, action: any): Channel {
|
|||||||
proxy: {
|
proxy: {
|
||||||
proxy: state?.proxy?.proxy || "",
|
proxy: state?.proxy?.proxy || "",
|
||||||
proxy_type: action.value as number,
|
proxy_type: action.value as number,
|
||||||
|
password: state?.proxy?.password || "",
|
||||||
|
username: state?.proxy?.username || "",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
case "set-proxy-username":
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
proxy: {
|
||||||
|
proxy: state?.proxy?.proxy || "",
|
||||||
|
proxy_type: state?.proxy?.proxy_type || 0,
|
||||||
|
password: state?.proxy?.password || "",
|
||||||
|
username: action.value as string,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
case "set-proxy-password":
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
proxy: {
|
||||||
|
proxy: state?.proxy?.proxy || "",
|
||||||
|
proxy_type: state?.proxy?.proxy_type || 0,
|
||||||
|
password: action.value as string,
|
||||||
|
username: state?.proxy?.username || "",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
case "set":
|
case "set":
|
||||||
|
@ -453,6 +453,38 @@ function ChannelEditor({
|
|||||||
disabled={edit.proxy?.proxy_type === 0}
|
disabled={edit.proxy?.proxy_type === 0}
|
||||||
/>
|
/>
|
||||||
</ParagraphItem>
|
</ParagraphItem>
|
||||||
|
<ParagraphItem>
|
||||||
|
<div className={`channel-content`}>
|
||||||
|
{t("admin.channels.proxy-username")}
|
||||||
|
</div>
|
||||||
|
<Input
|
||||||
|
value={edit.proxy?.username || ""}
|
||||||
|
placeholder={t("admin.channels.proxy-username-placeholder")}
|
||||||
|
onChange={(e) =>
|
||||||
|
dispatch({
|
||||||
|
type: "set-proxy-username",
|
||||||
|
value: e.target.value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
disabled={edit.proxy?.proxy_type === 0}
|
||||||
|
/>
|
||||||
|
</ParagraphItem>
|
||||||
|
<ParagraphItem>
|
||||||
|
<div className={`channel-content`}>
|
||||||
|
{t("admin.channels.proxy-password")}
|
||||||
|
</div>
|
||||||
|
<Input
|
||||||
|
value={edit.proxy?.password || ""}
|
||||||
|
placeholder={t("admin.channels.proxy-password-placeholder")}
|
||||||
|
onChange={(e) =>
|
||||||
|
dispatch({
|
||||||
|
type: "set-proxy-password",
|
||||||
|
value: e.target.value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
disabled={edit.proxy?.proxy_type === 0}
|
||||||
|
/>
|
||||||
|
</ParagraphItem>
|
||||||
<ParagraphDescription>
|
<ParagraphDescription>
|
||||||
{t("admin.channels.proxy-desc")}
|
{t("admin.channels.proxy-desc")}
|
||||||
</ParagraphDescription>
|
</ParagraphDescription>
|
||||||
|
@ -100,7 +100,7 @@ function SyncDialog({ dispatch, open, setOpen }: SyncDialogProps) {
|
|||||||
mapper: "",
|
mapper: "",
|
||||||
state: true,
|
state: true,
|
||||||
group: [],
|
group: [],
|
||||||
proxy: { proxy: "", proxy_type: 0 },
|
proxy: { proxy: "", proxy_type: 0, username: "", password: "" },
|
||||||
};
|
};
|
||||||
|
|
||||||
dispatch({ type: "set", value: data });
|
dispatch({ type: "set", value: data });
|
||||||
|
@ -633,6 +633,10 @@
|
|||||||
"proxy-type": "代理类型",
|
"proxy-type": "代理类型",
|
||||||
"proxy-endpoint": "代理地址",
|
"proxy-endpoint": "代理地址",
|
||||||
"proxy-endpoint-placeholder": "请输入正向代理地址,如:socks5://example.com:1080",
|
"proxy-endpoint-placeholder": "请输入正向代理地址,如:socks5://example.com:1080",
|
||||||
|
"proxy-username": "代理用户名",
|
||||||
|
"proxy-username-placeholder": "请输入代理的鉴权用户名 (可选)",
|
||||||
|
"proxy-password": "代理密码",
|
||||||
|
"proxy-password-placeholder": "请输入代理的鉴权密码 (可选)",
|
||||||
"proxy-desc": "正向代理,支持 HTTP/HTTPS/SOCKS5 代理 (反向代理请填写接入点, 非特殊情况无需设置正向代理)"
|
"proxy-desc": "正向代理,支持 HTTP/HTTPS/SOCKS5 代理 (反向代理请填写接入点, 非特殊情况无需设置正向代理)"
|
||||||
},
|
},
|
||||||
"charge": {
|
"charge": {
|
||||||
|
@ -461,7 +461,11 @@
|
|||||||
"proxy-type": "Delegate Type",
|
"proxy-type": "Delegate Type",
|
||||||
"proxy-endpoint": "proxy address",
|
"proxy-endpoint": "proxy address",
|
||||||
"proxy-endpoint-placeholder": "Please enter forward proxy address, ex: socks5://example.com: 1080",
|
"proxy-endpoint-placeholder": "Please enter forward proxy address, ex: socks5://example.com: 1080",
|
||||||
"proxy-desc": "Forward proxy, supports HTTP/HTTPS/SOCKS5 proxy (reverse proxy please fill in the access point, no need to set forward proxy in non-special cases)"
|
"proxy-desc": "Forward proxy, supports HTTP/HTTPS/SOCKS5 proxy (reverse proxy please fill in the access point, no need to set forward proxy in non-special cases)",
|
||||||
|
"proxy-username": "Proxy User",
|
||||||
|
"proxy-username-placeholder": "Please enter the agent's authentication username (optional)",
|
||||||
|
"proxy-password": "Proxy password",
|
||||||
|
"proxy-password-placeholder": "Please enter the agent's authentication password (optional)"
|
||||||
},
|
},
|
||||||
"charge": {
|
"charge": {
|
||||||
"id": "ID",
|
"id": "ID",
|
||||||
|
@ -461,7 +461,11 @@
|
|||||||
"proxy-type": "プロキシのタイプ",
|
"proxy-type": "プロキシのタイプ",
|
||||||
"proxy-endpoint": "プロキシアドレス",
|
"proxy-endpoint": "プロキシアドレス",
|
||||||
"proxy-endpoint-placeholder": "転送プロキシアドレスを入力してください。例: socks 5 :// example.com: 1080",
|
"proxy-endpoint-placeholder": "転送プロキシアドレスを入力してください。例: socks 5 :// example.com: 1080",
|
||||||
"proxy-desc": "フォワードプロキシ、HTTP/HTTPS/SOCKS 5プロキシをサポート(リバースプロキシはアクセスポイントに記入してください。特別な場合以外はフォワードプロキシを設定する必要はありません)"
|
"proxy-desc": "フォワードプロキシ、HTTP/HTTPS/SOCKS 5プロキシをサポート(リバースプロキシはアクセスポイントに記入してください。特別な場合以外はフォワードプロキシを設定する必要はありません)",
|
||||||
|
"proxy-username": "プロキシユーザー名",
|
||||||
|
"proxy-username-placeholder": "エージェントの認証ユーザー名を入力してください(オプション)",
|
||||||
|
"proxy-password": "プロキシパスワード",
|
||||||
|
"proxy-password-placeholder": "エージェントの認証パスワードを入力してください(オプション)"
|
||||||
},
|
},
|
||||||
"charge": {
|
"charge": {
|
||||||
"id": "ID",
|
"id": "ID",
|
||||||
|
@ -461,7 +461,11 @@
|
|||||||
"proxy-type": "Тип прокси- сервера",
|
"proxy-type": "Тип прокси- сервера",
|
||||||
"proxy-endpoint": "Адрес прокси-сервера",
|
"proxy-endpoint": "Адрес прокси-сервера",
|
||||||
"proxy-endpoint-placeholder": "Введите адрес прямого прокси-сервера, например: socks5://example.com: 1080",
|
"proxy-endpoint-placeholder": "Введите адрес прямого прокси-сервера, например: socks5://example.com: 1080",
|
||||||
"proxy-desc": "Прямой прокси-сервер, поддерживает HTTP/HTTPS/Socks5 прокси-сервер (обратный прокси-сервер, пожалуйста, заполните точку доступа, нет необходимости устанавливать прокси-сервер в неспециальных случаях)"
|
"proxy-desc": "Прямой прокси-сервер, поддерживает HTTP/HTTPS/Socks5 прокси-сервер (обратный прокси-сервер, пожалуйста, заполните точку доступа, нет необходимости устанавливать прокси-сервер в неспециальных случаях)",
|
||||||
|
"proxy-username": "Имя пользователя прокси-сервера",
|
||||||
|
"proxy-username-placeholder": "Введите имя пользователя для аутентификации агента (необязательно)",
|
||||||
|
"proxy-password": "Пароль прокси-сервера",
|
||||||
|
"proxy-password-placeholder": "Введите пароль аутентификации агента (необязательно)"
|
||||||
},
|
},
|
||||||
"charge": {
|
"charge": {
|
||||||
"id": "ID",
|
"id": "ID",
|
||||||
|
@ -49,4 +49,6 @@ type ListModelsItem struct {
|
|||||||
type ProxyConfig struct {
|
type ProxyConfig struct {
|
||||||
ProxyType int `json:"proxy_type" mapstructure:"proxytype"`
|
ProxyType int `json:"proxy_type" mapstructure:"proxytype"`
|
||||||
Proxy string `json:"proxy" mapstructure:"proxy"`
|
Proxy string `json:"proxy" mapstructure:"proxy"`
|
||||||
|
Username string `json:"username" mapstructure:"username"`
|
||||||
|
Password string `json:"password" mapstructure:"password"`
|
||||||
}
|
}
|
||||||
|
14
utils/net.go
14
utils/net.go
@ -38,6 +38,10 @@ func newClient(c []globals.ProxyConfig) *http.Client {
|
|||||||
|
|
||||||
if config.ProxyType == globals.HttpProxyType || config.ProxyType == globals.HttpsProxyType {
|
if config.ProxyType == globals.HttpProxyType || config.ProxyType == globals.HttpsProxyType {
|
||||||
proxyUrl, err := url.Parse(config.Proxy)
|
proxyUrl, err := url.Parse(config.Proxy)
|
||||||
|
if len(config.Username) > 0 || len(config.Password) > 0 {
|
||||||
|
proxyUrl.User = url.UserPassword(config.Username, config.Password)
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
globals.Warn(fmt.Sprintf("failed to parse proxy url: %s", err))
|
globals.Warn(fmt.Sprintf("failed to parse proxy url: %s", err))
|
||||||
return client
|
return client
|
||||||
@ -47,7 +51,15 @@ func newClient(c []globals.ProxyConfig) *http.Client {
|
|||||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||||
}
|
}
|
||||||
} else if config.ProxyType == globals.Socks5ProxyType {
|
} else if config.ProxyType == globals.Socks5ProxyType {
|
||||||
dialer, err := proxy.SOCKS5("tcp", config.Proxy, nil, proxy.Direct)
|
var auth *proxy.Auth
|
||||||
|
if len(config.Username) > 0 || len(config.Password) > 0 {
|
||||||
|
auth = &proxy.Auth{
|
||||||
|
User: config.Username,
|
||||||
|
Password: config.Password,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dialer, err := proxy.SOCKS5("tcp", config.Proxy, auth, proxy.Direct)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
globals.Warn(fmt.Sprintf("failed to create socks5 proxy: %s", err))
|
globals.Warn(fmt.Sprintf("failed to create socks5 proxy: %s", err))
|
||||||
return client
|
return client
|
||||||
|
Loading…
Reference in New Issue
Block a user