Trog Proxy - Discontinued
Note: This is not being sold anymore
TrogProxy is a proxy service that hides your server's IP while not hiding the original IP of the players.
Typically, players connected to a proxy will have their IPs hidden to rAthena; if the server bans the IP of the player, the proxy is useless. However, TrogProxy solves this issue. It also supports Packet Header Inspection, verifying that the first packet a client sends is valid BEFORE sending it to the server. This will prevent simple DDoS attacks.
Requirements
You must have ryml support in rAthena. This was merged in March 2022.
Set-Up
After you've followed the instructions below, send me the IP of your host and the ports you use, then I will give you a proxy_servers.yml that you will use.
Pricing
N/A
Instructions
You can find the diff here: https://gist.github.com/vstumpf/47051f55009bffbbb42462549de4b9a5
Alternatively, follow the steps below:
1) Create these files
1a) src/common/proxy.hpp
https://gist.github.com/vstumpf/4a60eab4592c8cd0bed32421d878ab74#file-proxy-hpp
1b) src/common/proxy.cpp
https://gist.github.com/vstumpf/4a60eab4592c8cd0bed32421d878ab74#file-proxy-cpp
1c) db/proxy_servers.yml
###########################################################################
# Proxy Database
###########################################################################
#
# Proxy Settings
#
###########################################################################
# - Name Name of the server, only used for logging. Can
# be anything, doesnt have to be unique.
# ProxyServer:
# PublicIP: Public IP or Hostname of the proxy server
# Port: Port of the proxy server
# LocalIP: IP to check for in case of subnet issues, docker containers, etc
# only read by proxy server
# TargetServer:
# PublicIP: Public IP or Hostname of the destination server
# Port: Port of the destination server
# LocalIP: IP to check for in case of subnet issues, docker containers, etc
# only read by target servers
# Secret: Secret to send to server
###########################################################################
Header:
Type: PROXY_DB
Version: 1
2) in src/char/char_clif.hpp
, after int chclif_parse(int fd);
add
void do_init_chclif(void);
void do_final_chclif(void);
3) in src/char/char_clif.cpp
3.1) Before #include "../common/malloc.hpp"
, add
#include "../common/proxy.hpp"
3.2) in chclif_parse_reqtoconnect()
, before ShowInfo("request connect - account_id:...");
add
session[fd]->flag.parsed = 1;
3.3) in chclif_send_map_data()
, remove
WFIFOL(fd,22) = htonl((subnet_map_ip) ? subnet_map_ip : map_server[map_server_index].ip);
WFIFOW(fd,26) = ntows(htons(map_server[map_server_index].port)); // [!] LE byte order here [!]
and add
auto * proxy = proxy_db.searchTargetIPPortProxyIp(map_server[map_server_index].ip, map_server[map_server_index].port, session[fd]->proxy_addr);
uint32 destip = map_server[map_server_index].ip;
uint16 destport = htons(map_server[map_server_index].port);
if (subnet_map_ip) {
destip = subnet_map_ip;
destport = htons(map_server[map_server_index].port);
}
if (proxy) {
destip = proxy->proxy.public_ip;
destport = ntohs(proxy->proxy.port);
}
WFIFOL(fd,22) = htonl(destip);
WFIFOW(fd,26) = ntows(destport); // [!] LE byte order here [!]
3.4) in chclif_parse()
, before // unknown packet received
, add
case 0xbeef: next = clif_parse_proxy(fd); break;
3.5) at the end of the file, add
/// Constructor destructor
/**
* Initialize the module.
* Launched at char-serv start, create db or other long scope variable here.
*/
void do_init_chclif(void){
proxy_db.load();
proxy_db.filterTargetIPPort(charserv_config.char_ip, charserv_config.char_port);
return;
}
/**
* chclif destructor
* dealloc..., function called at exit of the char-serv
*/
void do_final_chclif(void){
return;
}
4) in src/char/char.cpp
in do_init()
, after do_init_chmapif();
add
do_init_chclif();
5) In src/common/Makefile.in
5.1) After conf.o msg_conf.o cli.o sql.o database.o
, in the same line add proxy.o
, so it looks like:
conf.o msg_conf.o cli.o sql.o database.o proxy.o
5.2) After obj/mini%.o: %.cpp ...
, in the same line add $(RAPIDYAML_H)
, so it looks like:
obj/mini%.o: %.cpp $(COMMON_H) $(LIBCONFIG_H) $(YAML_CPP_H) $(RAPIDYAML_H)
5.3) Below 5.2
, After @@CXX@ @CXXFLAGS@ @CFLAGS_AR@ ...
, insert $(RAPIDYAML_INCLUDE)
so it looks like
@@CXX@ @CXXFLAGS@ @CFLAGS_AR@ $(LIBCONFIG_INCLUDE) $(RAPIDYAML_INCLUDE) $(YAML_CPP_INCLUDE) @MYSQL_CFLAGS@ -DMINICORE @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
6) In src/common/common.vcxproj
6.1) Before <ClInclude Include="random.hpp" />
, add
<ClInclude Include="proxy.hpp" />
6.2) Before <ClCompile Include="random.cpp" />
, add
<ClCompile Include="proxy.cpp />
7) In src/common/common.vcxproj.filters
7.1) Before <ClInclude Include="random.hpp">
, add
<ClInclude Include="proxy.hpp">
<Filter>Header Files</Filter>
</ClInclude>
7.2) Before <ClCompile Include="random.cpp">
, add
<ClCompile Include="proxy.cpp">
<Filter>Source Files</Filter>
</ClCompile>
8) In src/common/socket.hpp
8.1) In struct socket_data, after unsigned char ping : 2
; add
unsigned char parsed : 1;
8.2) After uint32 client_addr; // remote client address
, add
uint32 proxy_addr;
9) In src/common/socket.cpp
9.1) In connect_check_, before // Search the deny list
, add
// search the proxy list, always allow proxy servers
auto proxy = proxy_db.searchProxyIp(ip);
if (proxy) {
if (access_debug) {
ShowInfo("connect_check: Found match from proxy list:%d.%d.%d.%d IP:%d.%d.%d.%d\n",
CONVIP(ip),
CONVIP(proxy->proxy.public_ip));
}
is_allowip = 1;
}
9.2) In do_close, before sFD_CLR(fd, &readfds);
add
if (sFD_ISSET(fd, &readfds))
10) In src/login/loginclif.cpp
10.1) Before #include "../common/random.hpp"
, add
#include "../common/proxy.hpp"
10.2) In logclif_auth_ok()
, remove
WFIFOL(fd,header+n*size) = htonl((subnet_char_ip) ? subnet_char_ip : ch_server[i].ip);
WFIFOW(fd,header+n*size+4) = ntows(htons(ch_server[i].port)); // [!] LE byte order here [!]
and add
auto * proxy = proxy_db.searchTargetIPPortProxyIp(ch_server[i].ip, ch_server[i].port, session[fd]->proxy_addr);
ShowInfo("Proxy addr is %s\n", ip2str(session[fd]->proxy_addr, nullptr));
uint32 destip = ch_server[i].ip;
uint16 destport = htons(ch_server[i].port);
if (subnet_char_ip) {
destip = subnet_char_ip;
destport = htons(ch_server[i].port);
}
if (proxy) {
destip = proxy->proxy.public_ip;
destport = ntohs(proxy->proxy.port);
ShowInfo("Using proxy! sending %s\n", ip2str(destip, nullptr));
}
WFIFOL(fd,header+n*size) = htonl(destip);
WFIFOW(fd,header+n*size+4) = ntows(destport); // [!] LE byte order here [!]
10.3) in logclif_parse_updclhash
, after size_t packet_len = RFIFOREST(fd);
add
// Perform ip-ban check
if( login_config.ipban && ipban_check(session[fd]->client_addr) )
{
ShowStatus("Connection refused: IP isn't authorised (deny/allow, ip: %s).\n", ip);
login_log(session[fd]->client_addr, "unknown", -3, "ip banned");
logclif_auth_failed(sd, 3);
set_eof(fd);
return 0;
}
session[fd]->flag.parsed = 1;
10.4) In logclif_parse()
, before default:
, add
case 0xbeef: next = clif_parse_proxy(fd); break;
10.5) In do_init_loginclif()
, add
proxy_db.load();
proxy_db.filterTargetIPPort(login_config.login_ip, login_config.login_port);
11) In src/map/clif.cpp
11.1) Before #include "../common/random.hpp"
add
#include "../common/proxy.hpp"
11.2) In clif_parse_WantToConnection()
, after t_tick client_tick;
add
session[fd]->flag.parsed = 1;
11.3) Before clif_parse
, create the new function:
int clif_parse_proxy_closing(int fd) {
const size_t packet_len = 4;
if (RFIFOREST(fd) < packet_len)
return 0;
if (!session[fd]->session_data)
return 0;
uint16 mins = RFIFOW(fd, 2);
char msg[CHAT_SIZE_MAX];
safesnprintf(msg, CHAT_SIZE_MAX, "Please relog before auto-disconnect, %d minutes remaining.", mins);
clif_broadcast(&((TBL_PC *)session[fd]->session_data)->bl, msg, strlen(msg) + 1, 0, SELF);
RFIFOSKIP(fd, packet_len);
return 1;
}
11.4) In clif_parse
, before // filter out invalid / unsupported packets
add
if (cmd == 0xbeef) {
if (clif_parse_proxy(fd) == 0)
return 0;
continue;
}
if (cmd == 0xbeee && sd) {
if (clif_parse_proxy_closing(fd) == 0)
return 0;
continue;
}
11.5) In do_init_clif()
, before delay_clearunit_ers = ers_new(...);
add
proxy_db.load();
proxy_db.filterTargetIPPort(bind_ip, map_port);