2010-04-29 35 views
5

Tôi có một chương trình nghe trên cổng 443 và sau đó chuyển hướng đến máy chủ cục bộ SSH hoặc HTTPS tùy thuộc vào giao thức được phát hiện.Proxy trong suốt - cách truyền socket đến máy chủ cục bộ mà không sửa đổi?

Chương trình thực hiện việc này bằng cách kết nối với máy chủ cục bộ và ủy quyền tất cả dữ liệu qua lại thông qua quy trình của riêng nó.

Tuy nhiên, điều này làm cho máy chủ có nguồn gốc trên máy chủ cục bộ được đăng nhập dưới dạng máy chủ cục bộ.

Có cách nào để chuyển socket trực tiếp đến quy trình máy chủ cục bộ (thay vì chỉ tạo kết nối TCP mới) để các tham số của sockaddr_in (hoặc) sẽ được giữ lại không?

Nền tảng cho điều này là Linux.

Trả lời

6

Nếu bạn có quyền kiểm soát các quy trình máy chủ cục bộ, thì bạn có thể thực hiện việc này. Tạo một kết nối ổ cắm miền UNIX liên tục giữa quá trình proxy và quy trình máy chủ, sau đó sử dụng sendmsg() trên ổ cắm miền UNIX đó để chuyển thông báo SCM_RIGHTS chứa bộ mô tả tệp của trình cắm TCP. Quá trình proxy sau đó có thể đóng xử lý của nó vào ổ cắm TCP.

Khi quy trình máy chủ được chuyển qua bộ mô tả tệp từ proxy trong thông báo SCM_RIGHTS, nó chỉ cần thêm nó vào bộ ổ cắm khách bình thường, như thể nó đến từ accept().

+0

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 –

7

Đâ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 
+0

Cảm ơn lời khuyên! nhưng tiếc là kỹ thuật đó dường như không hoạt động khi máy chủ đích là localhost –

+0

@Luca Farber: Tôi đã thêm một số thông tin được lấy từ câu hỏi thường gặp về stunnel. Hãy thử điều đó. –

+0

Hmm, mặc dù không quan tâm nhiều đến nó, tôi dường như không thể vượt qua được kết nối(), nơi nó bị treo. "netstat -a -n" hiển thị kết nối trong trạng thái SYN_SENT (với máy chủ/cổng từ xa làm nguồn và 127.0.0.1:localport làm đích). –

1

Sử dụng https://stackoverflow.com/a/2741535/388191, nó có thể làm điều này với lượng truy cập vào máy chủ cục bộ bằng cách sử dụng connmark để theo dõi các kết nối trong suốt địa phương đến và đánh dấu các gói tin gửi đi để định tuyến lại cho họ trở lại máy chủ địa phương:

iptables -t mangle -N DIVERT 
iptables -t mangle -A PREROUTING -i lo -p tcp -m socket -j DIVERT 
iptables -t mangle -A DIVERT -j CONNMARK --set-mark 2 
iptables -t mangle -A DIVERT -j ACCEPT 
iptables -t mangle -A OUTPUT -m connmark --mark 2 -j MARK --set-mark 1 
ip rule add fwmark 1 lookup 100 
ip route add local 0.0.0.0/0 dev lo table 100 
Các vấn đề liên quan