- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个基于 Boost ASIO 的 C++ 服务器程序,我希望能够将 TCP 使用的源 IP 地址设置为另一台服务器的源 IP 地址。我知道可以读取源 IP 地址和目标 IP 地址,但大概也可以设置它们?
大概如果我在 C++ 代码中设置了“错误”的源 IP 地址,将会与网络堆栈进行一些交互。即使 C++ 代码是正确的,网络堆栈不会在退出时重新设置源 IP 地址吗?正确的方法是编写 C++ ASIO 代码来选择特定的虚拟网络接口(interface)吗?一个配置了“错误的”静态 IP 地址?我之前已经看到这是一种控制源 IP 地址的方法。这是我需要做的吗?
我想知道这会带来什么后果。将两台机器配置为相同的静态 IP 地址可能会导致“正常”服务器完全停止工作,这很糟糕。
我可以使用我的服务器的 Windows 和 Linux 端口,以防建议的代码在一个操作系统上运行而不在另一个操作系统上运行。我目前倾向于使用 Kali Linux,因为我可以“欺骗”主服务器并有效地将其关闭一段时间。
最佳答案
通过手动构建网络和传输层 header ,然后将 header 和所需的有效负载发送到 raw socket,可以将源 IP 设置为出站数据的任意地址。 .使用原始套接字可能需要提升权限,或者可能被内核禁用或限制,例如在某些 Microsoft platforms 上.此外,由于 TCP 的三次握手和不可预测的序列号,伪造的 TCP 段的有效性超出了潜在的TCP reset attacks。 , 值得怀疑。
路由是一个不同的主题,取决于各种路由器和配置。例如,设备可能会执行导出过滤并丢弃带有设备无法验证的源地址的数据包。此外,IP 地址冲突的影响可能会有所不同,但通常会导致间歇性连接。
Boost.Asio 提供了一个 basic_raw_socket<Protocol>
需要符合 Protocol 类型的模板类型要求。例如,下面是开始或 raw
协议(protocol):
struct raw
{
typedef boost::asio::ip::basic_endpoint<raw> endpoint;
int type() const { return SOCK_RAW; }
int protocol() const { return IPPROTO_RAW; }
int family() const { return PF_INET; }
};
boost::asio::basic_raw_socket<raw> socket;
在处理原始套接字时,困难通常不在于使用 Boost.Asio,而在于必须实现网络和传输线协议(protocol)。下面是一个完整的最小示例,我试图通过创建一个 raw
来使其尽可能简单。协议(protocol)和使用 basic_raw_socket
发送 UDP 消息:
#include <algorithm>
#include <iostream>
#include <boost/array.hpp>
#include <boost/asio.hpp>
#include <boost/cstdint.hpp>
/// @brief raw socket provides the protocol for raw socket.
class raw
{
public:
///@brief The type of a raw endpoint.
typedef boost::asio::ip::basic_endpoint<raw> endpoint;
///@brief The raw socket type.
typedef boost::asio::basic_raw_socket<raw> socket;
///@brief The raw resolver type.
typedef boost::asio::ip::basic_resolver<raw> resolver;
///@brief Construct to represent the IPv4 RAW protocol.
static raw v4()
{
return raw(IPPROTO_RAW, PF_INET);
}
///@brief Construct to represent the IPv6 RAW protocol.
static raw v6()
{
return raw(IPPROTO_RAW, PF_INET6);
}
///@brief Default constructor.
explicit raw()
: protocol_(IPPROTO_RAW),
family_(PF_INET)
{}
///@brief Obtain an identifier for the type of the protocol.
int type() const
{
return SOCK_RAW;
}
///@brief Obtain an identifier for the protocol.
int protocol() const
{
return protocol_;
}
///@brief Obtain an identifier for the protocol family.
int family() const
{
return family_;
}
///@brief Compare two protocols for equality.
friend bool operator==(const raw& p1, const raw& p2)
{
return p1.protocol_ == p2.protocol_ && p1.family_ == p2.family_;
}
/// Compare two protocols for inequality.
friend bool operator!=(const raw& p1, const raw& p2)
{
return !(p1 == p2);
}
private:
explicit raw(int protocol_id, int protocol_family)
: protocol_(protocol_id),
family_(protocol_family)
{}
int protocol_;
int family_;
};
///@ brief Mockup ipv4_header for with no options.
//
// IPv4 wire format:
//
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-------+-------+-------+-------+-------+-------+-------+------+ ---
// |version|header | type of | total length in bytes | ^
// | (4) | length| service | | |
// +-------+-------+-------+-------+-------+-------+-------+------+ |
// | identification |flags| fragment offset | |
// +-------+-------+-------+-------+-------+-------+-------+------+ 20 bytes
// | time to live | protocol | header checksum | |
// +-------+-------+-------+-------+-------+-------+-------+------+ |
// | source IPv4 address | |
// +-------+-------+-------+-------+-------+-------+-------+------+ |
// | destination IPv4 address | v
// +-------+-------+-------+-------+-------+-------+-------+------+ ---
// / options (if any) /
// +-------+-------+-------+-------+-------+-------+-------+------+
class ipv4_header
{
public:
ipv4_header() { std::fill(buffer_.begin(), buffer_.end(), 0); }
void version(boost::uint8_t value) {
buffer_[0] = (value << 4) | (buffer_[0] & 0x0F);
}
void header_length(boost::uint8_t value)
{
buffer_[0] = (value & 0x0F) | (buffer_[0] & 0xF0);
}
void type_of_service(boost::uint8_t value) { buffer_[1] = value; }
void total_length(boost::uint16_t value) { encode16(2, value); }
void identification(boost::uint16_t value) { encode16(4, value); }
void dont_fragment(bool value)
{
buffer_[6] ^= (-value ^ buffer_[6]) & 0x40;
}
void more_fragments(bool value)
{
buffer_[6] ^= (-value ^ buffer_[6]) & 0x20;
}
void fragment_offset(boost::uint16_t value)
{
// Preserve flags.
auto flags = static_cast<uint16_t>(buffer_[6] & 0xE0) << 8;
encode16(6, (value & 0x1FFF) | flags);
}
void time_to_live(boost::uint8_t value) { buffer_[8] = value; }
void protocol(boost::uint8_t value) { buffer_[9] = value; }
void checksum(boost::uint16_t value) { encode16(10, value); }
void source_address(boost::asio::ip::address_v4 value)
{
auto bytes = value.to_bytes();
std::copy(bytes.begin(), bytes.end(), &buffer_[12]);
}
void destination_address(boost::asio::ip::address_v4 value)
{
auto bytes = value.to_bytes();
std::copy(bytes.begin(), bytes.end(), &buffer_[16]);
}
public:
std::size_t size() const { return buffer_.size(); }
const boost::array<uint8_t, 20>& data() const { return buffer_; }
private:
void encode16(boost::uint8_t index, boost::uint16_t value)
{
buffer_[index] = (value >> 8) & 0xFF;
buffer_[index + 1] = value & 0xFF;
}
boost::array<uint8_t, 20> buffer_;
};
void calculate_checksum(ipv4_header& header)
{
// Zero out the checksum.
header.checksum(0);
// Checksum is the 16-bit one's complement of the one's complement sum of
// all 16-bit words in the header.
// Sum all 16-bit words.
auto data = header.data();
auto sum = std::accumulate<boost::uint16_t*, boost::uint32_t>(
reinterpret_cast<boost::uint16_t*>(&data[0]),
reinterpret_cast<boost::uint16_t*>(&data[0] + data.size()),
0);
// Fold 32-bit into 16-bits.
while (sum >> 16)
{
sum = (sum & 0xFFFF) + (sum >> 16);
}
header.checksum(~sum);
}
///@brief Mockup IPv4 UDP header.
//
// UDP wire format:
//
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-------+-------+-------+-------+-------+-------+-------+------+ ---
// | source port | destination port | ^
// +-------+-------+-------+-------+-------+-------+-------+------+ 8 bytes
// | length | checksum | v
// +-------+-------+-------+-------+-------+-------+-------+------+ ---
// / data (if any) /
// +-------+-------+-------+-------+-------+-------+-------+------+
class udp_header
{
public:
udp_header() { std::fill(buffer_.begin(), buffer_.end(), 0); }
void source_port(boost::uint16_t value) { encode16(0, value); }
void destination_port(boost::uint16_t value) { encode16(2, value); }
void length(boost::uint16_t value) { encode16(4, value); }
void checksum(boost::uint16_t value) { encode16(6, value); }
public:
std::size_t size() const { return buffer_.size(); }
const boost::array<uint8_t, 8>& data() const { return buffer_; }
private:
void encode16(boost::uint8_t index, boost::uint16_t value)
{
buffer_[index] = (value >> 8) & 0xFF;
buffer_[index + 1] = value & 0xFF;
}
boost::array<uint8_t, 8> buffer_;
};
int main()
{
boost::asio::io_service io_service;
// Create all I/O objects.
boost::asio::ip::udp::socket receiver(io_service,
boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 0));
boost::asio::basic_raw_socket<raw> sender(io_service,
raw::endpoint(raw::v4(), 0));
const auto receiver_endpoint = receiver.local_endpoint();
// Craft a UDP message with a payload 'hello' coming from
// 8.8.8.8:54321
const boost::asio::ip::udp::endpoint spoofed_endpoint(
boost::asio::ip::address_v4::from_string("8.8.8.8"),
54321);
const std::string payload = "hello";
// Create the UDP header.
udp_header udp;
udp.source_port(spoofed_endpoint.port());
udp.destination_port(receiver_endpoint.port());
udp.length(udp.size() + payload.size()); // Header + Payload
udp.checksum(0); // Optioanl for IPv4
// Create the IPv4 header.
ipv4_header ip;
ip.version(4); // IPv4
ip.header_length(ip.size() / 4); // 32-bit words
ip.type_of_service(0); // Differentiated service code point
auto total_length = ip.size() + udp.size() + payload.size();
ip.total_length(total_length); // Entire message.
ip.identification(0);
ip.dont_fragment(true);
ip.more_fragments(false);
ip.fragment_offset(0);
ip.time_to_live(4);
ip.source_address(spoofed_endpoint.address().to_v4());
ip.destination_address(receiver_endpoint.address().to_v4());
ip.protocol(IPPROTO_UDP);
calculate_checksum(ip);
// Gather up all the buffers and send through the raw socket.
boost::array<boost::asio::const_buffer, 3> buffers = {{
boost::asio::buffer(ip.data()),
boost::asio::buffer(udp.data()),
boost::asio::buffer(payload)
}};
auto bytes_transferred = sender.send_to(buffers,
raw::endpoint(receiver_endpoint.address(), receiver_endpoint.port()));
assert(bytes_transferred == total_length);
// Read on the reciever.
std::vector<char> buffer(payload.size(), '\0');
boost::asio::ip::udp::endpoint sender_endpoint;
bytes_transferred = receiver.receive_from(
boost::asio::buffer(buffer), sender_endpoint);
// Verify.
assert(bytes_transferred == payload.size());
assert(std::string(buffer.begin(), buffer.end()) == payload);
assert(spoofed_endpoint == sender_endpoint);
// Print endpoints.
std::cout <<
"Actual sender endpoint: " << sender.local_endpoint() << "\n"
"Receiver endpoint: " << receiver.local_endpoint() << "\n"
"Receiver's remote endpoint: " << sender_endpoint << std::endl;
}
输出:
$ sudo ./a.out
Actual sender endpoint: 0.0.0.0:255
Receiver endpoint: 0.0.0.0:44806
Receiver's remote endpoint: 8.8.8.8:54321
如输出所示,尽管真正的发送端点是 0.0.0.0:255
,接收方认为发送方的端点是 8.8.8.8:54321
.
关于c++ - 在 Boost ASIO 中,如何设置源 IP 地址以模拟另一台服务器的 IP 地址?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28196466/
使用 asio 库,我想为 asio::serial_port 读/写调用使用超时。 是否可以使用相同的 asio::serial_port asio::io_context 和用于 asio 的相同
对于我正在从事的副业项目应该使用哪种类型的解析器,我有点困惑。我在 asio 文档中找不到答案。 我知道 DNS 可以与 UDP 或 TCP 一起使用,并且通常通过 TCP 发送较大的响应。 asio
在仅从一个线程调用 io_service::run() 的情况下,从不同线程调用 async_write 和 async_read 是否安全?谢谢! 最佳答案 Is it safe to call a
我想知道Boost ASIO 有多受欢迎。它是否被用于任何流行的网络密集型软件中? 最佳答案 用于管理 IBM Blue Gene/Q 的系统软件 super 计算机广泛使用Boost.Asio。
我想使用一个函数来读取套接字端口,并在收到 IP 数据包时交还控制权。 boost::asio::ip::udp::socket 有一个函数接收(或 async_receive),它返回读取了多少字节
我试图调整 Boost 文档中的 SSL 服务器示例 here但我想制作一个应用程序,您可以在其中使用普通 boost::asio::ip::tcp::socket或 SSL 套接字,但我还没有找到将
在查看 boost asio co_spawn 文档 ( https://www.boost.org/doc/libs/1_78_0/doc/html/boost_asio/reference/co_
我正在尝试使用 Boost.ASIO 库,但我找不到如何列出 boost 的可用端口(带有串行端口服务)或套接字(带有网络服务)。 你知道这是否可能吗? 谢谢你。 最佳答案 Boost.Asio 不提
我想使用boost::asio从多个stdout中同时读取stderr和boost::process。但是,我在使用boost::asio时遇到了编译问题,可以重建以下无法编译的最小示例: #incl
提前为一个愚蠢的问题道歉 - 我对这一切都很陌生。 所以我从 here 下载了 asio ,并尝试#include asio.hpp,但出现以下错误; fatal error: boost/confi
我是使用 boost 的项目的一部分作为一个 C++ 库。现在我们要使用 SMTP/POP3/SSL/HTTP/HTTPS。我在 Poco::Net 中检测到几个拟合类和函数 Poco::Net::P
有谁知道有任何实现 Web Sockets 的尝试吗?使用 Boost asio 的 API? 最佳答案 我意识到这是一个旧线程,但想更新以帮助那些寻找答案的人:WebSocket++完全符合要求。
和 asio::thread_pool 有什么区别和一个 asio::io_context谁的run()函数是从多个线程调用的?我可以更换我的 boost::thread_group调用 io_con
我想连接到由目标 IP 地址和端口号指定的服务器套接字。 boost::asio::connect 似乎不允许使用它。我有 ip 目的地作为无符号 int 值。 更新:我能够做到 ba::ip::tc
我在 pc 上有 3 个网络接口(interface),并且想确保当我进行 udp 套接字发送时,它通过特定的网络接口(interface)发送(我有发送数据时使用的 ip 地址)。 这是代码。 ud
我正在使用 ASIO 开发网络应用程序并提到了Chat-Server/Client 我问过类似的问题Here 为了更好地解释,我在这里添加了更多代码: 我的 Cserver Class class C
我已经阅读了 boost asio 引用资料,浏览了教程并查看了一些示例。尽管如此,我还是看不出应该如何拆除套接字: 我应该调用 close() 还是由套接字的析构函数完成? 什么时候应该调用 shu
我认为标题已经说明了大部分内容,但我也有兴趣了解在没有现有解决方案的情况下如何将 DTLS 支持引入 asio 最佳答案 ASIO 本身不支持DTLS 但有一个GitHub 库asio_dtls已向
我正在将 async_read 与 streambuf 一起使用。但是,我想将读取的数据量限制为 4,这样我就可以在进入正文之前正确处理 header 。 我如何使用 async_read 做到这一点
从this example开始,我想用 async_read_until() 替换 async_read()。 所以我查了一下this example ,并查看了如何调用 async_read_unt
我是一名优秀的程序员,十分优秀!