Skip to content

Commit

Permalink
Add region filter
Browse files Browse the repository at this point in the history
  • Loading branch information
Jackarain committed Jan 12, 2024
1 parent 1bcd3b3 commit f7c64c1
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 0 deletions.
99 changes: 99 additions & 0 deletions proxy/include/proxy/proxy_server.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
#include "proxy/default_cert.hpp"
#include "proxy/fileop.hpp"
#include "proxy/strutil.hpp"
#include "proxy/ipip.hpp"

#include "proxy/socks_enums.hpp"
#include "proxy/socks_client.hpp"
Expand Down Expand Up @@ -269,6 +270,18 @@ R"x*x*x(<html>
using auth_users = std::tuple<std::string, std::string>;
std::vector<auth_users> auth_users_;

// allow_regions/deny_regions 用于指定允许/拒绝的地区, 例如:
// allow_regions_ = { "中国", "香港", "台湾" };
// deny_regions_ = { "美国", "日本" };
// allow_regions/deny_regions 为空时, 表示不限制地区.
// 必须在设置了 ipip 数据库文件后才能生效.
std::vector<std::string> allow_regions_;
std::vector<std::string> deny_regions_;

// ipip 数据库文件, 用于指定 ipip 数据库文件, 用于地区限制.
// ipip 数据库文件可以从: https://www.ipip.net 下载.
std::string ipip_db_;

// 多层代理, 当前服务器级连下一个服务器, 对于 client 而言是无感的,
// 这是当前服务器通过 proxy_pass_ 指定的下一个代理服务器, 为 client
// 实现多层代理.
Expand Down Expand Up @@ -4072,6 +4085,13 @@ R"x*x*x(<html>

boost::system::error_code ec;

if (fs::exists(m_option.ipip_db_, ec))
{
m_ipip = std::make_unique<ipip_datx>();
if (!m_ipip->load(m_option.ipip_db_))
m_ipip.reset();
}

m_acceptor.open(endp.protocol(), ec);
if (ec)
{
Expand Down Expand Up @@ -4328,11 +4348,38 @@ R"x*x*x(<html>
auto client = endp.address().to_string();
client += ":" + std::to_string(endp.port());

std::vector<std::string> local_info;

if (m_ipip)
{
auto [ret, isp] = m_ipip->lookup(endp.address());
if (!ret.empty())
{
for (auto& c : ret)
client += " " + c;

local_info = ret;
}

if (!isp.empty())
client += " " + isp;
}

XLOG_DBG << "connection id: "
<< connection_id
<< ", start client incoming: "
<< client;

if (!region_filter(local_info))
{
XLOG_WARN << "connection id: "
<< connection_id
<< ", region filter: "
<< client;

continue;
}

socket.set_option(keep_alive_opt, error);

// 是否启用透明代理.
Expand Down Expand Up @@ -4490,6 +4537,55 @@ R"x*x*x(<html>
}
}

bool region_filter(const std::vector<std::string>& local_info) const noexcept
{
auto& deny_region = m_option.deny_regions_;
auto& allow_region = m_option.allow_regions_;

std::optional<bool> allow;

if (m_ipip && (!allow_region.empty() || !deny_region.empty()))
{
for (auto& region : allow_region)
{
for (auto& l : local_info)
{
if (l.starts_with(region))
{
allow.emplace(true);
break;
}
}

if (allow)
break;
}

if (!allow)
{
for (auto& region : deny_region)
{
for (auto& l : local_info)
{
if (l.starts_with(region))
{
allow.emplace(false);
break;
}
}

if (allow)
break;
}
}
}

if (!allow)
return true;

return *allow;
}

private:
// m_executor 保存当前 io_context 的 executor.
net::any_io_executor m_executor;
Expand All @@ -4503,6 +4599,9 @@ R"x*x*x(<html>
// 当前机器的所有 ip 地址.
std::set<net::ip::address> m_local_addrs;

// ipip 用于获取 ip 地址的地理位置信息.
std::unique_ptr<ipip> m_ipip;

using proxy_session_weak_ptr =
std::weak_ptr<proxy_session>;

Expand Down
13 changes: 13 additions & 0 deletions server/proxy_server/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ namespace fs = std::filesystem;
#include "proxy/logging.hpp"

#include "proxy/use_awaitable.hpp"
#include "proxy/ipip.hpp"

#include "main.hpp"

Expand All @@ -45,6 +46,10 @@ using server_ptr = std::shared_ptr<proxy_server>;


std::vector<std::string> auth_users;
std::vector<std::string> deny_region;
std::vector<std::string> allow_region;

std::string ipip_db;
std::string doc_dir;
std::string log_dir;
std::string local_ip;
Expand Down Expand Up @@ -127,6 +132,10 @@ start_proxy_server(net::io_context& ioc, server_ptr& server)
opt.noise_length_ = noise_length;
opt.local_ip_ = local_ip;

opt.ipip_db_ = ipip_db;
opt.deny_regions_ = deny_region;
opt.allow_regions_ = allow_region;

opt.reuse_port_ = reuse_port;
opt.happyeyeballs_ = happyeyeballs;
opt.connect_v4_only_ = connect_v4only;
Expand Down Expand Up @@ -257,6 +266,9 @@ int main(int argc, char** argv)

("auth_users", po::value<std::vector<std::string>>(&auth_users)->multitoken()->default_value(std::vector<std::string>{"jack:1111"}), "List of authorized users(default user: jack:1111) (e.g: user1:passwd1 user2:passwd2).")

("allow_region", po::value<std::vector<std::string>>(&allow_region)->multitoken(), "Allow region (e.g: 北京|河南|武汉).")
("deny_region", po::value<std::vector<std::string>>(&deny_region)->multitoken(), "Deny region (e.g: 广东|上海|山东).")

("proxy_pass", po::value<std::string>(&proxy_pass)->default_value("")->value_name(""), "Specify next proxy pass (e.g: socks5://user:passwd@ip:port).")
("proxy_pass_ssl", po::value<bool>(&proxy_pass_ssl)->default_value(false, "false")->value_name(""), "Enable SSL for the next proxy pass.")

Expand All @@ -271,6 +283,7 @@ int main(int argc, char** argv)
("ssl_ciphers", po::value<std::string>(&ssl_ciphers)->value_name("ssl_ciphers"), "Specify enabled SSL ciphers")
("ssl_prefer_server_ciphers", po::value<bool>(&ssl_prefer_server_ciphers)->default_value(false, "false")->value_name(""), "Prefer server ciphers over client ciphers for SSLv3 and TLS protocols.")

("ipip_db", po::value<std::string>(&ipip_db)->value_name("")->default_value("17monipdb.datx"), "Specify ipip database filename.")
("http_doc", po::value<std::string>(&doc_dir)->value_name("doc"), "Specify document root directory for HTTP server.")
("autoindex", po::value<bool>(&autoindex)->default_value(false), "Enable directory listing.")
("logs_path", po::value<std::string>(&log_dir)->value_name(""), "Specify directory for log files.")
Expand Down

0 comments on commit f7c64c1

Please sign in to comment.