How can I send through a specific network interface?

耗尽温柔 提交于 2020-02-25 04:06:53

问题


I need send messages through different gateways dynamically. How do that and what must be my first step in this direction?

On my server I have two connections: one-direct, and secondary over VPN. Default route is direct connection, but i need dynamically change connection to VPN.

At current time I try build socket from libc::bind() it's work, but have not expected effect.

Changing the outgoing IP is not a solution to define the interface.


回答1:


As suggested in a comment we must use SO_BINDTODEVICE, and no way to escape FFI cause it used internally. Here working example:

extern crate libc;

use libc as c;
use std::ffi::CString;
use std::net::{TcpStream, SocketAddr};
use std::io::{self, Write};
use std::os::unix::io::FromRawFd;
use std::mem;

#[cfg(any(target_os = "linux"))]
fn connect_dev(addr: SocketAddr, link: &str) -> io::Result<TcpStream> {
    let (addr_raw, addr_len) = match addr {
        SocketAddr::V4(ref a) =>
            (a as *const _ as *const _, mem::size_of_val(a) as c::socklen_t),
        SocketAddr::V6(ref a) =>
            (a as *const _ as *const _, mem::size_of_val(a) as c::socklen_t),
    };

    unsafe {
        let fd = check_os_error(c::socket(c::AF_INET, c::SOCK_STREAM, 0))?;
        check_os_error(c::setsockopt(
            fd,
            c::SOL_SOCKET,
            c::SO_BINDTODEVICE,
            CString::new(link).expect("device name").as_ptr() as *const c::c_void,
            mem::size_of::<CString>() as c::socklen_t,
        ))?;
        check_os_error(c::connect(fd, addr_raw, addr_len))?;

        Ok(TcpStream::from_raw_fd(fd))
    }
}

#[cfg(any(target_os = "linux"))]
pub fn check_os_error(res: c::c_int) -> io::Result<c::c_int> {
    if res == -1 {
        Err(io::Error::from_raw_os_error(unsafe { *c::__errno_location()  as i32 }))
    } else {
        Ok(res)
    }
}



回答2:


You can use a different source IPs. I assume that you have your system configured to route different source IPs into different gateways (if not, it's an operator problem, not a programmer). You can specify different source IP in bind function for socket. Normally you pass their 'default' value (0.0.0.0) which means 'anything OS find reasonable', but you can specify exact source IP for your task.

A C bind signature:

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

addr may contain the specific address.



来源:https://stackoverflow.com/questions/52257027/how-can-i-send-through-a-specific-network-interface

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!