Đây là đoạn mã được lấy từ stunnel (từ client.c trong hàm local_bind nếu bạn muốn xem tất cả mã).
#ifdef IP_TRANSPARENT
int on=1;
if(c->opt->option.transparent) {
if(setsockopt(c->fd, SOL_IP, IP_TRANSPARENT, &on, sizeof on))
sockerror("setsockopt IP_TRANSPARENT");
/* ignore the error to retain Linux 2.2 compatibility */
/* the error will be handled by bind(), anyway */
}
#endif /* IP_TRANSPARENT */
memcpy(&addr, &c->bind_addr.addr[0], sizeof addr);
if(ntohs(addr.in.sin_port)>=1024) { /* security check */
if(!bind(c->fd, &addr.sa, addr_len(addr))) {
s_log(LOG_INFO, "local_bind succeeded on the original port");
return; /* success */
}
if(get_last_socket_error()!=EADDRINUSE
#ifndef USE_WIN32
|| !c->opt->option.transparent
#endif /* USE_WIN32 */
) {
sockerror("local_bind (original port)");
longjmp(c->err, 1);
}
}
Trước đó, c-> bind_addr được thành lập đến địa chỉ của các peer kết nối với mã này:
else if(c->opt->option.transparent)
memcpy(&c->bind_addr, &c->peer_addr, sizeof(SOCKADDR_LIST));
Các tài liệu stunnel chứa lời khuyên này cho Linux kernel gần đây:
Chế độ từ xa (hoặc 2.2.x và> = 2.6.28) yêu cầu stunnel phải được thực thi dưới dạng root. tùy chọn setuid cũng sẽ phá vỡ chức năng này.
Linux> = 2.6.28 đòi hỏi các thiết lập sau đây cho iptables và định tuyến (có thể trong file cục bộ hoặc tương đương):
iptables -t mangle -N DIVERT
iptables -t mangle -A PREROUTING -p tcp -m socket -j DIVERT
iptables -t mangle -A DIVERT -j MARK --set-mark 1
iptables -t mangle -A DIVERT -j ACCEPT
ip rule add fwmark 1 lookup 100
ip route add local 0.0.0.0/0 dev lo table 100
Nguồn
2010-04-30 00:04:50
Nhờ đó là rất thú vị, mặc dù tiếc là tôi không có đồng ntrol trên các máy chủ địa phương; về cơ bản chúng là hộp đen –