Feature: Integrate frp client with master program

This commit is contained in:
yuanyuanxiang
2025-07-31 19:45:46 +08:00
parent d2b7c32206
commit f7e4e7a9d3
14 changed files with 245 additions and 13 deletions

View File

@@ -19,6 +19,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
ReadMe_EN.md = ReadMe_EN.md
使用方法.txt = 使用方法.txt
使用花生壳.txt = 使用花生壳.txt
反向代理.md = 反向代理.md
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TinyRun", "client\TinyRun.vcxproj", "{E3F3A477-05BA-431D-B002-28EF8BFA6E86}"

View File

@@ -174,6 +174,8 @@
这种情况在生成服务端程序时IP填写的是VPS的IP有些VPS供应商甚至提供域名则填写域名也可以。通常在VPS上运行FRP服务程序
在本地运行FRP客户端程序。当有主机连接VPS时则VPS这个中间人会把请求转发到本地计算机而我们发起的控制请求也将经这个中间人打到受控主机。
有关跨网、跨境或跨国远程控制系统的部署方式,详见:[反向代理部署说明](./反向代理.md),这是作者实践和所使用的方式。
# 5.更新日志 <a id="5-changelog"></a>
2025年以前的变更记录参看[history](./history.md)

View File

@@ -9,15 +9,19 @@
class config
{
private:
char m_IniFilePath[_MAX_PATH];
char m_IniFilePath[_MAX_PATH] = { 0 };
public:
virtual ~config() {}
config()
config(const std::string& path="")
{
::GetModuleFileNameA(NULL, m_IniFilePath, sizeof(m_IniFilePath));
GET_FILEPATH(m_IniFilePath, "settings.ini");
if (path.length() == 0) {
::GetModuleFileNameA(NULL, m_IniFilePath, sizeof(m_IniFilePath));
GET_FILEPATH(m_IniFilePath, "settings.ini");
} else {
memcpy(m_IniFilePath, path.c_str(), path.length());
}
}
virtual int GetInt(const std::string& MainKey, const std::string& SubKey, int nDef=0)

Binary file not shown.

View File

@@ -185,6 +185,22 @@ std::string GetDbPath() {
return dbPath;
}
std::string GetFrpSettingsPath() {
#ifdef _DEBUG
char path[MAX_PATH];
GetModuleFileNameA(NULL, path, MAX_PATH);
GET_FILEPATH(path, "frpc.ini");
return path;
#else
static char path[MAX_PATH], * name = "frpc.ini";
static std::string ret = (FAILED(SHGetFolderPathA(NULL, CSIDL_APPDATA, NULL, 0, path)) ? "." : path)
+ std::string("\\YAMA\\");
static BOOL ok = CreateDirectoryA(ret.c_str(), NULL);
static std::string p = ret + name;
return p;
#endif
}
std::string GetFileName(const char* filepath) {
const char* slash1 = strrchr(filepath, '/');
const char* slash2 = strrchr(filepath, '\\');
@@ -406,6 +422,7 @@ BEGIN_MESSAGE_MAP(CMy2015RemoteDlg, CDialogEx)
ON_MESSAGE(WM_UPXTASKRESULT, UPXProcResult)
ON_MESSAGE(WM_PASSWORDCHECK, OnPasswordCheck)
ON_MESSAGE(WM_SHOWMESSAGE, OnShowMessage)
ON_MESSAGE(WM_SHOWERRORMSG, OnShowErrMessage)
ON_WM_HELPINFO()
ON_COMMAND(ID_ONLINE_SHARE, &CMy2015RemoteDlg::OnOnlineShare)
ON_COMMAND(ID_TOOL_AUTH, &CMy2015RemoteDlg::OnToolAuth)
@@ -690,6 +707,21 @@ VOID CMy2015RemoteDlg::ShowMessage(CString strType, CString strMsg)
m_StatusBar.SetPaneText(0,strStatusMsg); //在状态条上显示文字
}
LRESULT CMy2015RemoteDlg::OnShowErrMessage(WPARAM wParam, LPARAM lParam) {
CString* text = (CString*)wParam;
CString err = *text;
delete text;
CTime Timer = CTime::GetCurrentTime();
CString strTime = Timer.Format("%H:%M:%S");
m_CList_Message.InsertItem(0, "操作错误");
m_CList_Message.SetItemText(0, 1, strTime);
m_CList_Message.SetItemText(0, 2, err);
return S_OK;
}
extern "C" BOOL ConvertToShellcode(LPVOID inBytes, DWORD length, DWORD userFunction,
LPVOID userData, DWORD userLength, DWORD flags, LPSTR * outBytes, DWORD * outLength);
@@ -1003,9 +1035,86 @@ BOOL CMy2015RemoteDlg::OnInitDialog()
"请设置\"公网IP\"或使用反向代理服务器的IP";
ShowMessage("使用提示", tip);
#ifdef _WIN64
if (!master.empty()) {
int use = THIS_CFG.GetInt("frp", "UseFrp");
if (use) {
m_hFRPThread = CreateThread(NULL, 0, StartFrpClient, this, NULL, NULL);
}
}
#endif
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
DWORD WINAPI CMy2015RemoteDlg::StartFrpClient(LPVOID param){
CMy2015RemoteDlg* This = (CMy2015RemoteDlg*)param;
Mprintf("[FRP] Proxy thread start running\n");
do
{
DWORD size = 0;
LPBYTE frpc = ReadResource(IDR_BINARY_FRPC, size);
if (frpc == nullptr) {
Mprintf("Failed to read FRP DLL\n");
break;
}
HMEMORYMODULE hDLL = MemoryLoadLibrary(frpc, size);
SAFE_DELETE_ARRAY(frpc);
if (hDLL == NULL) {
Mprintf("Failed to load FRP DLL\n");
break;
}
typedef int (*Run)(char* cstr, int* ptr);
Run run = (Run)MemoryGetProcAddress(hDLL, "Run");
if (!run) {
Mprintf("Failed to get FRP function\n");
MemoryFreeLibrary(hDLL);
break;
}
std::string s = GetFrpSettingsPath();
int n = run((char*)s.c_str(), &(This->m_frpStatus));
if (n) {
Mprintf("Failed to run FRP function\n");
This->PostMessage(WM_SHOWERRORMSG,(WPARAM)new CString("反向代理: 公网IP和代理设置是否正确? FRP 服务端是否运行?"));
}
// Free FRP DLL will cause crash
// Do NOT use MemoryFreeLibrary and 528 bytes memory leak detected when exiting master
// MemoryFreeLibrary(hDLL);
} while (false);
CloseHandle(This->m_hFRPThread);
This->m_hFRPThread = NULL;
Mprintf("[FRP] Proxy thread stop running\n");
return 0x20250731;
}
void CMy2015RemoteDlg::ApplyFrpSettings() {
auto master = THIS_CFG.GetStr("settings", "master");
if (master.empty()) return;
config cfg(GetFrpSettingsPath());
cfg.SetStr("common", "server_addr", master);
cfg.SetInt("common", "server_port", THIS_CFG.GetInt("frp", "server_port", 7000));
cfg.SetStr("common", "token", THIS_CFG.GetStr("frp", "token"));
cfg.SetStr("common", "log_file", THIS_CFG.GetStr("frp", "log_file", "./frpc.log"));
auto ports = THIS_CFG.GetStr("settings", "ghost", "6543");
auto arr = StringToVector(ports, ';');
for (int i = 0; i < arr.size(); ++i) {
auto tcp = "YAMA-TCP-" + arr[i];
cfg.SetStr(tcp, "type", "tcp");
cfg.SetStr(tcp, "local_port", arr[i]);
cfg.SetStr(tcp, "remote_port", arr[i]);
auto udp = "YAMA-UDP-" + arr[i];
cfg.SetStr(udp, "type", "udp");
cfg.SetStr(udp, "local_port", arr[i]);
cfg.SetStr(udp, "remote_port", arr[i]);
}
}
void CMy2015RemoteDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
@@ -1203,6 +1312,7 @@ void CMy2015RemoteDlg::Release(){
Mprintf("======> Release\n");
DeletePopupWindow();
isClosed = TRUE;
m_frpStatus = STATUS_EXIT;
ShowWindow(SW_HIDE);
Shell_NotifyIcon(NIM_DELETE, &m_Nid);
@@ -1218,6 +1328,8 @@ void CMy2015RemoteDlg::Release(){
}
LeaveCriticalSection(&m_cs);
Sleep(500);
while (m_hFRPThread)
Sleep(20);
THIS_APP->Destroy();
g_2015RemoteDlg = NULL;
@@ -1619,9 +1731,26 @@ void CMy2015RemoteDlg::OnMainSet()
{
CSettingDlg Dlg;
Dlg.m_nMax_Connect = m_nMaxConnection;
BOOL use = THIS_CFG.GetInt("frp", "UseFrp");
int port = THIS_CFG.GetInt("frp", "server_port", 7000);
auto token = THIS_CFG.GetStr("frp", "token");
auto ret = Dlg.DoModal(); //模态 阻塞
if (ret != IDOK) return;
Dlg.DoModal(); //模态 阻塞
BOOL use_new = THIS_CFG.GetInt("frp", "UseFrp");
int port_new = THIS_CFG.GetInt("frp", "server_port", 7000);
auto token_new = THIS_CFG.GetStr("frp", "token");
ApplyFrpSettings();
if (use_new != use) {
MessageBoxA("修改FRP代理开关需要重启当前应用程序方可生效。", "提示", MB_ICONINFORMATION);
} else if (port != port_new || token != token_new) {
m_frpStatus = STATUS_STOP;
Sleep(200);
m_frpStatus = STATUS_RUN;
}
if (use && use_new && m_hFRPThread == NULL) {
MessageBoxA("FRP代理服务异常需要重启当前应用程序进行重试。", "提示", MB_ICONINFORMATION);
}
int m = atoi(THIS_CFG.GetStr("settings", "ReportInterval", "5").c_str());
int n = THIS_CFG.GetInt("settings", "SoftwareDetect");
if (m== m_settings.ReportInterval && n == m_settings.DetectSoftware) {

View File

@@ -155,7 +155,7 @@ public:
void SortByColumn(int nColumn);
afx_msg VOID OnHdnItemclickList(NMHDR* pNMHDR, LRESULT* pResult);
static int CALLBACK CompareFunction(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);
template<class T, int id, int Show=SW_SHOW> LRESULT OpenDialog(WPARAM wParam, LPARAM lParam)
template<class T, int id, int Show = SW_SHOW> LRESULT OpenDialog(WPARAM wParam, LPARAM lParam)
{
CONTEXT_OBJECT* ContextObject = (CONTEXT_OBJECT*)lParam;
T* Dlg = new T(this, ContextObject->GetServer(), ContextObject);
@@ -169,15 +169,15 @@ public:
}
VOID InitControl(); //<2F><>ʼ<EFBFBD>ؼ<EFBFBD>
VOID TestOnline(); //<2F><><EFBFBD>Ժ<EFBFBD><D4BA><EFBFBD>
VOID AddList(CString strIP, CString strAddr, CString strPCName, CString strOS, CString strCPU, CString strVideo, CString strPing,
CString ver, CString startTime, const std::vector<std::string> &v, CONTEXT_OBJECT* ContextObject);
VOID AddList(CString strIP, CString strAddr, CString strPCName, CString strOS, CString strCPU, CString strVideo, CString strPing,
CString ver, CString startTime, const std::vector<std::string>& v, CONTEXT_OBJECT* ContextObject);
VOID ShowMessage(CString strType, CString strMsg);
VOID CreatStatusBar();
VOID CreateToolBar();
VOID CreateNotifyBar();
VOID CreateSolidMenu();
VOID CreateSolidMenu();
int m_nMaxConnection;
BOOL Activate(const std::string& nPort,int nMaxConnection, const std::string& method);
BOOL Activate(const std::string& nPort, int nMaxConnection, const std::string& method);
void UpdateActiveWindow(CONTEXT_OBJECT* ctx);
void SendMasterSettings(CONTEXT_OBJECT* ctx);
VOID SendServerDll(CONTEXT_OBJECT* ContextObject, bool isDLL, bool is64Bit);
@@ -189,8 +189,8 @@ public:
VOID MessageHandle(CONTEXT_OBJECT* ContextObject);
VOID SendSelectedCommand(PBYTE szBuffer, ULONG ulLength);
// <20><>ʾ<EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
CWnd* m_pFloatingTip=nullptr;
CListCtrl m_CList_Online;
CWnd* m_pFloatingTip = nullptr;
CListCtrl m_CList_Online;
CListCtrl m_CList_Message;
void DeletePopupWindow();
@@ -206,6 +206,16 @@ public:
CMenu m_MainMenu;
CBitmap m_bmOnline[15];
uint64_t m_superID;
enum {
STATUS_UNKNOWN = -1,
STATUS_RUN = 0,
STATUS_STOP = 1,
STATUS_EXIT = 2,
};
HANDLE m_hFRPThread = NULL;
int m_frpStatus = STATUS_RUN;
static DWORD WINAPI StartFrpClient(LPVOID param);
void ApplyFrpSettings();
bool CheckValid(int trail = 14);
afx_msg void OnTimer(UINT_PTR nIDEvent);
afx_msg void OnClose();
@@ -281,4 +291,5 @@ public:
afx_msg void OnOnlineAddWatch();
afx_msg void OnNMCustomdrawOnline(NMHDR* pNMHDR, LRESULT* pResult);
afx_msg void OnOnlineRunAsAdmin();
afx_msg LRESULT OnShowErrMessage(WPARAM wParam, LPARAM lParam);
};

View File

@@ -242,6 +242,7 @@
<None Include="res\Cur\MutiDrag.cur" />
<None Include="res\dword.ico" />
<None Include="res\file.ico" />
<None Include="res\frpc.dll" />
<None Include="res\My2015Remote.rc2" />
<None Include="res\pc.ico" />
<None Include="res\string.ico" />

View File

@@ -188,6 +188,7 @@
<None Include="res\pc.ico" />
<None Include="res\string.ico" />
<None Include="res\upx.exe" />
<None Include="res\frpc.dll" />
</ItemGroup>
<ItemGroup>
<Text Include="..\..\ReadMe.md" />

View File

@@ -22,6 +22,8 @@ CSettingDlg::CSettingDlg(CWnd* pParent)
, m_sSoftwareDetect(_T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ"))
, m_sPublicIP(_T(""))
, m_sUdpOption(_T(""))
, m_nFrpPort(7000)
, m_sFrpToken(_T(""))
{
}
@@ -53,6 +55,12 @@ void CSettingDlg::DoDataExchange(CDataExchange* pDX)
DDX_Control(pDX, IDC_EDIT_UDP_OPTION, m_EditUdpOption);
DDX_Text(pDX, IDC_EDIT_UDP_OPTION, m_sUdpOption);
DDV_MaxChars(pDX, m_sUdpOption, 24);
DDX_Control(pDX, IDC_EDIT_FRP_PORT, m_EditFrpPort);
DDX_Text(pDX, IDC_EDIT_FRP_PORT, m_nFrpPort);
DDV_MinMaxInt(pDX, m_nFrpPort, 1, 65535);
DDX_Control(pDX, IDC_EDIT_FRP_TOKEN, m_EditFrpToken);
DDX_Text(pDX, IDC_EDIT_FRP_TOKEN, m_sFrpToken);
DDV_MaxChars(pDX, m_sFrpToken, 24);
}
BEGIN_MESSAGE_MAP(CSettingDlg, CDialog)
@@ -61,6 +69,8 @@ BEGIN_MESSAGE_MAP(CSettingDlg, CDialog)
ON_EN_CHANGE(IDC_EDIT_MAX, &CSettingDlg::OnEnChangeEditMax)
ON_BN_CLICKED(IDC_RADIO_ALL_SCREEN, &CSettingDlg::OnBnClickedRadioAllScreen)
ON_BN_CLICKED(IDC_RADIO_MAIN_SCREEN, &CSettingDlg::OnBnClickedRadioMainScreen)
ON_BN_CLICKED(IDC_RADIO_FRP_OFF, &CSettingDlg::OnBnClickedRadioFrpOff)
ON_BN_CLICKED(IDC_RADIO_FRP_ON, &CSettingDlg::OnBnClickedRadioFrpOn)
END_MESSAGE_MAP()
@@ -126,6 +136,13 @@ BOOL CSettingDlg::OnInitDialog()
BOOL all = THIS_CFG.GetInt("settings", "MultiScreen");
((CButton*)GetDlgItem(IDC_RADIO_ALL_SCREEN))->SetCheck(!all);
((CButton*)GetDlgItem(IDC_RADIO_MAIN_SCREEN))->SetCheck(all);
BOOL frp = THIS_CFG.GetInt("frp", "UseFrp");
((CButton*)GetDlgItem(IDC_RADIO_FRP_OFF))->SetCheck(!frp);
((CButton*)GetDlgItem(IDC_RADIO_FRP_ON))->SetCheck(frp);
m_nFrpPort = THIS_CFG.GetInt("frp", "server_port", 7000);
m_sFrpToken = THIS_CFG.GetStr("frp", "token").c_str();
UpdateData(FALSE);
return TRUE;
@@ -152,6 +169,11 @@ void CSettingDlg::OnBnClickedButtonSettingapply()
BOOL all = ((CButton*)GetDlgItem(IDC_RADIO_MAIN_SCREEN))->GetCheck();
THIS_CFG.SetInt("settings", "MultiScreen", all);
BOOL frp = ((CButton*)GetDlgItem(IDC_RADIO_FRP_ON))->GetCheck();
THIS_CFG.SetInt("frp", "UseFrp", frp);
THIS_CFG.SetInt("frp", "server_port", m_nFrpPort);
THIS_CFG.SetStr("frp", "token", m_sFrpToken.GetString());
m_ApplyButton.EnableWindow(FALSE);
m_ApplyButton.ShowWindow(SW_HIDE);
}
@@ -206,3 +228,17 @@ void CSettingDlg::OnBnClickedRadioMainScreen()
BOOL b = ((CButton*)GetDlgItem(IDC_RADIO_MAIN_SCREEN))->GetCheck();
((CButton*)GetDlgItem(IDC_RADIO_ALL_SCREEN))->SetCheck(!b);
}
void CSettingDlg::OnBnClickedRadioFrpOff()
{
BOOL b = ((CButton*)GetDlgItem(IDC_RADIO_FRP_OFF))->GetCheck();
((CButton*)GetDlgItem(IDC_RADIO_FRP_ON))->SetCheck(!b);
}
void CSettingDlg::OnBnClickedRadioFrpOn()
{
BOOL b = ((CButton*)GetDlgItem(IDC_RADIO_FRP_ON))->GetCheck();
((CButton*)GetDlgItem(IDC_RADIO_FRP_OFF))->SetCheck(!b);
}

View File

@@ -42,4 +42,10 @@ public:
afx_msg void OnBnClickedRadioMainScreen();
CEdit m_EditUdpOption;
CString m_sUdpOption;
afx_msg void OnBnClickedRadioFrpOff();
afx_msg void OnBnClickedRadioFrpOn();
CEdit m_EditFrpPort;
int m_nFrpPort;
CEdit m_EditFrpToken;
CString m_sFrpToken;
};

Binary file not shown.

Binary file not shown.

View File

@@ -88,6 +88,7 @@
#define WM_OPENDRAWINGBOARD WM_USER+3020
#define WM_PASSWORDCHECK WM_USER+3021
#define WM_SHOWMESSAGE WM_USER+3022
#define WM_SHOWERRORMSG WM_USER+3023
#ifdef _UNICODE
#if defined _M_IX86

40
反向代理.md Normal file
View File

@@ -0,0 +1,40 @@
## <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD>v1.1.5<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>س<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>FRP<EFBFBD>ͻ<EFBFBD><EFBFBD>˽<EFBFBD><EFBFBD>м<EFBFBD><EFBFBD>ɣ<EFBFBD><EFBFBD>Ա<EFBFBD><EFBFBD><EFBFBD>֧<EFBFBD>ֿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͹<EFBFBD><EFBFBD>ҵ<EFBFBD>Զ<EFBFBD>̿<EFBFBD><EFBFBD>ơ<EFBFBD>
FRP<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD>ٷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Go<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͸<EFBFBD><EFBFBD><EFBFBD>ߣ<EFBFBD><EFBFBD>ɰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> NAT <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǽ<EFBFBD><C7BD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><C4B1>ط<EFBFBD><D8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><C2B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>õĵ<EFBFBD>FRP<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>޸ģ<EFBFBD><EFBFBD>ֿ<EFBFBD><EFBFBD><EFBFBD>ַΪ<EFBFBD><EFBFBD>https://github.com/yuanyuanxiang/frp
## ʹ<>÷<EFBFBD><C3B7><EFBFBD>
1.FRP<52><50><EFBFBD><EFBFBD><EFBFBD>˵İ<CBB5>װ
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD>[FRP<EFBFBD>ٷ<EFBFBD>](https://github.com/fatedier/frp/releases)<29>ֿ<EFBFBD><D6BF><EFBFBD><EFBFBD>ط<EFBFBD><D8B7><EFBFBD><EFBFBD>˳<EFBFBD><CBB3><EFBFBD>"frps"<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>s<EFBFBD><73>׺<EFBFBD><D7BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD>ˡ<EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>Ϊfrps.ini<6E><69>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD>£<EFBFBD>
```ini
[common]
bind_port = 7000
token=1234567a
dashboard_port = 7500 # <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ļ<EFBFBD>
dashboard_user = admin # <20><><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1>
dashboard_pwd = admin123 # <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EBA3A8>ѡ<EFBFBD><D1A1>
```
<EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"bind_port"֮<><EFBFBD><E2A3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>DZ<EFBFBD><C7B1><EFBFBD><EFBFBD><EFBFBD><EEA3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>дtoken<65><6E><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>κοͻ<CEBF><CDBB>˾<EFBFBD><CBBE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӡ<EFBFBD>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>LinuxΪ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>nohup ./frps -c frps.ini > frps.log 2>&1 &
2.FRP<52>ͻ<EFBFBD><CDBB>˵<EFBFBD>ʹ<EFBFBD><CAB9>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>س<EFBFBD><EFBFBD><EFBFBD>YAMA<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD>
* <20><><EFBFBD><EFBFBD>IP<49><50><EFBFBD>˼<EFBFBD>FRP<52><50><EFBFBD><EFBFBD><EFBFBD><EFBFBD>IP<49><50>FRP<52><50><EFBFBD><EFBFBD><EFBFBD>˱<EFBFBD><CBB1>벿<EFBFBD><EBB2BF><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>й<EFBFBD><D0B9><EFBFBD>IP<49>ķ<EFBFBD><C4B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* FRP<52><50><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD>ã<EFBFBD><C3A3><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><D0B4><EFBFBD><EFBFBD><EFBFBD>˿ڣ<CBBF>FRP<52><50><EFBFBD><EFBFBD><EFBFBD>˶˿ڣ<CBBF><DAA3><EFBFBD><EFBFBD><EFBFBD>frps.ini<6E>ļ<EFBFBD><C4BC>е<EFBFBD>"bind_port"<22><><EFBFBD><EFBFBD>token
ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>YAMAʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>FRP<EFBFBD>ͻ<EFBFBD><EFBFBD>ˣ<EFBFBD>ȷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ؽ<EFBFBD><EFBFBD>п<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD>̿<EFBFBD><EFBFBD>ơ<EFBFBD>
## <20><><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>VPS<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD>̿<EFBFBD><EFBFBD>ơ<EFBFBD>ֻ<EFBFBD><EFBFBD>Ҫÿ<EFBFBD><EFBFBD>3~10ŷ<30><C5B7><EFBFBD><EFBFBD><EFBFBD>ɴһ<EEBDA8><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϳ<EFBFBD><CDBF><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD>̿<EFBFBD><CCBF><EFBFBD>ϵͳ<CFB5><CDB3>
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴˣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>VPS<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>VPNʹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><EFBFBD><EFBFBD><EFBFBD>VSP<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ר<EFBFBD><EFBFBD>VPN<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¡<EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֲ<EFBFBD>Ϊ<EFBFBD><EFBFBD>