Có một nhị phân mà tôi cần chạy, sử dụng bind
với đối số cổng bằng 0, để có được một cổng miễn phí ngẫu nhiên từ hệ thống. Có cách nào để tôi có thể giới hạn phạm vi cổng mà kernel được phép chọn không?
Có một nhị phân mà tôi cần chạy, sử dụng bind
với đối số cổng bằng 0, để có được một cổng miễn phí ngẫu nhiên từ hệ thống. Có cách nào để tôi có thể giới hạn phạm vi cổng mà kernel được phép chọn không?
Câu trả lời:
trên Linux, bạn sẽ làm một cái gì đó như
sudo sysctl -w net.ipv4.ip_local_port_range="60000 61000"
có thể tìm thấy hướng dẫn thay đổi phạm vi cổng phù du trên các thông báo khác tại http://www.ncftp.com/ncftpd/doc/misc/ephemeral_ports.html
Nếu bạn muốn thay đổi cách một nhị phân chạy mà không có quyền truy cập vào các nguồn của nó, đôi khi bạn có thể sử dụng một shim, một đoạn mã, trong ví dụ của bạn, sẽ thay thế cuộc gọi bind()
bằng một cuộc gọi đến một chức năng mà bạn cung cấp có thể thao tác dữ liệu trước khi gọi hàm thực. Xem LD_PRELOAD
trong man ld.so
.
Đây là một số C thực hiện chính xác điều đó, shim_bind.c, ghi đè cổng lên 7777 và giả sử ổ cắm AF_INET. Biên dịch nó với gcc -Wall -O2 -fpic -shared -ldl -o shim_bind.so shim_bind.c
và sử dụng nó bằng cách đặt LD_PRELOAD=shim_bind.so
trước lệnh của bạn.
/*
* capture calls to a routine and replace with your code
* http://unix.stackexchange.com/a/305336/119298
* gcc -Wall -O2 -fpic -shared -ldl -o shim_bind.so shim_bind.c
* LD_PRELOAD=/path/to/shim_bind.so ./test
*/
#define _GNU_SOURCE /* needed to get RTLD_NEXT defined in dlfcn.h */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <dlfcn.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen){
static int (*real_bind)(int sockfd, const struct sockaddr *addr,
socklen_t addrlen) = NULL;
int port = 7777;
struct sockaddr_in theaddr;
if (!real_bind) {
real_bind = dlsym(RTLD_NEXT, "bind");
char *error = dlerror();
if (error != NULL) {
fprintf(stderr, "%s\n", error);
exit(1);
}
}
fprintf(stderr, "binding: port %d\n", port);
memcpy(&theaddr, addr, sizeof(theaddr));
theaddr.sin_port = htons((unsigned short)port);
return real_bind(sockfd, (struct sockaddr*)&theaddr, addrlen);
}
ip_local_port_range
sẽ dễ dàng hơn để thiết lập ngay bây giờ, nhưng có lẽ tôi sẽ cần chơi với các cuộc gọi khác trên tệp nhị phân này để việc này có vẻ rất hữu ích, cảm ơn!