diff --git a/2019Remote.sln b/2019Remote.sln index 1fbb683..07cd2f0 100644 --- a/2019Remote.sln +++ b/2019Remote.sln @@ -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}" diff --git a/ReadMe.md b/ReadMe.md index 053d059..fcd2461 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -174,6 +174,8 @@ 这种情况,在生成服务端程序时,IP填写的是VPS的IP,有些VPS供应商甚至提供域名,则填写域名也可以。通常,在VPS上运行FRP服务程序, 在本地运行FRP客户端程序。当有主机连接VPS时,则VPS这个中间人会把请求转发到本地计算机,而我们发起的控制请求也将经这个中间人打到受控主机。 +有关跨网、跨境或跨国远程控制系统的部署方式,详见:[反向代理部署说明](./反向代理.md),这是作者实践和所使用的方式。 + # 5.更新日志 2025年以前的变更记录参看:[history](./history.md) diff --git a/common/iniFile.h b/common/iniFile.h index 0ddf44f..3af85ef 100644 --- a/common/iniFile.h +++ b/common/iniFile.h @@ -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) diff --git a/server/2015Remote/2015Remote.rc b/server/2015Remote/2015Remote.rc index 995d327..596ecae 100644 Binary files a/server/2015Remote/2015Remote.rc and b/server/2015Remote/2015Remote.rc differ diff --git a/server/2015Remote/2015RemoteDlg.cpp b/server/2015Remote/2015RemoteDlg.cpp index b863ed3..76a6da9 100644 --- a/server/2015Remote/2015RemoteDlg.cpp +++ b/server/2015Remote/2015RemoteDlg.cpp @@ -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) { diff --git a/server/2015Remote/2015RemoteDlg.h b/server/2015Remote/2015RemoteDlg.h index 32c7bd6..e106723 100644 --- a/server/2015Remote/2015RemoteDlg.h +++ b/server/2015Remote/2015RemoteDlg.h @@ -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 LRESULT OpenDialog(WPARAM wParam, LPARAM lParam) + template 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(); //ʼؼ VOID TestOnline(); //Ժ - VOID AddList(CString strIP, CString strAddr, CString strPCName, CString strOS, CString strCPU, CString strVideo, CString strPing, - CString ver, CString startTime, const std::vector &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& 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); // ʾûϢ - 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); }; diff --git a/server/2015Remote/2015Remote_vs2015.vcxproj b/server/2015Remote/2015Remote_vs2015.vcxproj index 2a59802..19f82b2 100644 --- a/server/2015Remote/2015Remote_vs2015.vcxproj +++ b/server/2015Remote/2015Remote_vs2015.vcxproj @@ -242,6 +242,7 @@ + diff --git a/server/2015Remote/2015Remote_vs2015.vcxproj.filters b/server/2015Remote/2015Remote_vs2015.vcxproj.filters index 2314989..c98d6b1 100644 --- a/server/2015Remote/2015Remote_vs2015.vcxproj.filters +++ b/server/2015Remote/2015Remote_vs2015.vcxproj.filters @@ -188,6 +188,7 @@ + diff --git a/server/2015Remote/SettingDlg.cpp b/server/2015Remote/SettingDlg.cpp index c134c64..ed99996 100644 --- a/server/2015Remote/SettingDlg.cpp +++ b/server/2015Remote/SettingDlg.cpp @@ -22,6 +22,8 @@ CSettingDlg::CSettingDlg(CWnd* pParent) , m_sSoftwareDetect(_T("ͷ")) , 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); +} diff --git a/server/2015Remote/SettingDlg.h b/server/2015Remote/SettingDlg.h index 24c85db..f655e9b 100644 --- a/server/2015Remote/SettingDlg.h +++ b/server/2015Remote/SettingDlg.h @@ -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; }; diff --git a/server/2015Remote/res/frpc.dll b/server/2015Remote/res/frpc.dll new file mode 100644 index 0000000..6292d4f Binary files /dev/null and b/server/2015Remote/res/frpc.dll differ diff --git a/server/2015Remote/resource.h b/server/2015Remote/resource.h index 51a0dc4..d906da3 100644 Binary files a/server/2015Remote/resource.h and b/server/2015Remote/resource.h differ diff --git a/server/2015Remote/stdafx.h b/server/2015Remote/stdafx.h index 5a71f4b..f19e002 100644 --- a/server/2015Remote/stdafx.h +++ b/server/2015Remote/stdafx.h @@ -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 diff --git a/反向代理.md b/反向代理.md new file mode 100644 index 0000000..ae14dd0 --- /dev/null +++ b/反向代理.md @@ -0,0 +1,40 @@ +## + +v1.1.5汾سͷFRPͻ˽мɣԱֿ֧͹ҵԶ̿ơ +FRPΪٷһGo͸ߣɰ NAT ǽıط¶ +ʹõĵFRPΪ䣬޸ģַֿΪhttps://github.com/yuanyuanxiang/frp + +## ʹ÷ + +1.FRP˵İװ + +Դ[FRPٷ](https://github.com/fatedier/frp/releases)ֿط˳"frps"s׺Ƿˡ +˵ļΪfrps.iniʾ£ + +```ini +[common] +bind_port = 7000 +token=1234567a +dashboard_port = 7500 # ҪĻ +dashboard_user = admin # ûѡ +dashboard_pwd = admin123 # 루ѡ +``` + +У"bind_port"֮⣬DZдtokenκοͻ˾ӡ + +LinuxΪnohup ./frps -c frps.ini > frps.log 2>&1 & + +2.FRPͻ˵ʹ + +سYAMAȷѡ + +* IP˼FRPIPFRP˱벿һйIPķ棩 +* FRPѡãд˿ڣFRP˶˿ڣfrps.iniļе"bind_port"token + +ÿYAMAʱԶFRPͻˣȷؽпԶ̿ơ + +## ʵ + +ʹVPSԶ̿ơֻҪÿ3~10ŷɴһͿԶ̿ϵͳ + +ڴˣһVPSVPNʹôVSPרVPN¡һãֲΪ