로컬 Linux 시스템 A에서 실행되는 애플리케이션이 있고 포트 12325에서 수신 대기하는 다른 시스템 B와 통신할 수 있어야 합니다. 기본적으로 장치가 통신할 수 없는 경우 문제가 발생하므로 ACL에서 포트 12325를 열었지만 소스 머신 A의 애플리케이션 포트는 무작위입니다. iptables를 사용하여 변경하려는 애플리케이션의 소스 포트를 12325로 구체적으로 변환할 수 있나요? 항상 동일한 사용자, 동일한 위치에서 실행됩니다.
- 소프트웨어는 오픈 소스가 아니므로 이 소프트웨어 측면을 강요할 수는 없습니다.
- 시스템 간의 모든 포트를 열 수 없습니다.
답변1
옵션 1: 컨테이너
명시적인 IP 주소를 사용하여 컨테이너 내에서 애플리케이션을 실행한 다음 아웃바운드 연결을 허용하도록 로컬 방화벽 규칙을 수정합니다.해당 특정 IP 주소에서. 이렇게 하면 포트를 알 필요가 없습니다. 해당 IP 주소와 관련된 규칙은 해당 애플리케이션의 연결에만 영향을 미치고 다른 것에는 영향을 미치지 않는다는 것을 알 수 있습니다. 이는 다음과 같을 수 있습니다:
docker network create app_network --subnet 192.168.51.0/24
docker run --network my_app_network --ip 192.168.51.10 myapimage ...
그런 다음 로컬 방화벽에 다음과 같은 항목을 추가할 수 있습니다.
iptables -A FORWARD -s 192.168.51.10/32 -j ACCEPT
옵션 2: 함수 삽입
애플리케이션이 동적으로 링크된 실행 파일이라고 가정하면 다음을 사용할 수 있습니다.함수 삽입특정 라이브러리 호출을 재정의합니다. 이 경우 연결이 설정되기 전에 호출되도록 connect
호출을 재정의할 수 있습니다. bind
이는 다음과 같을 수 있습니다:
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdint.h>
#include <dlfcn.h>
#ifndef TARGET_PORT
#define TARGET_PORT 80
#endif
#ifndef SOURCE_PORT
#define SOURCE_PORT 12000
#endif
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
static int (*real_connect)(int, const struct sockaddr *, socklen_t) = NULL;
if (!real_connect)
real_connect = dlsym(RTLD_NEXT, "connect");
/*
* Only makes changes if you are initiating an AF_INET connection to
* a specific remote port. Modify the logic here, or modify
* TARGET_PORT and SOURCE_PORT, above, to change this behavior.
*/
if (
addr->sa_family == AF_INET &&
((struct sockaddr_in *)addr)->sin_port == htons(TARGET_PORT)
) {
const int enable = 1;
// Set SO_REUSEADDR, otherwise subsequent connections will fail until
// the socket exits the TIME_WAIT state.
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0)
return -1;
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(INADDR_ANY);
sin.sin_port = htons(SOURCE_PORT);
if (bind(sockfd, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
return -1;
}
}
return real_connect(sockfd, addr, addrlen);
}
코드를 공유 라이브러리로 컴파일합니다.
gcc -shared -ldl -fPIC connect_with_port.c -o connect_with_port.so
그런 다음 다음을 사용하여 활성화하십시오 LD_PRELOAD
.
LD_PRELOAD=./connect_with_port.so nc google.com 80
위의 명령을 실행하면 tcpdump
연결이 port 에서 시작되는 것을 볼 수 있습니다 12000
.