그래서 최근에 파일을 통해 TCP 패킷을 보내는 방법을 알아냈는데 /dev/tcp/hostname/port
, 가장 큰 문제는 그것을 어떻게 받는가 입니다. TCP 서버를 호스팅할 수 있는 bash 스크립트와 TCP 클라이언트 역할을 하는 또 다른 스크립트를 만들고 싶습니다. 약간의 도움이 좋을 것입니다. 나는 또한 이것을 학습 경험으로 하고 있다는 점을 지적하고 싶습니다. 이것이 내가 원하는 작업을 수행하는 방법으로 ssh
또는를 사용하지 않는 이유입니다.telnet
답변1
~에 따르면이것, 아니요. bash
시도하지 않았기 때문에 할 수 없습니다.bind(2)
소켓이지만 시도해 보세요.connect(2)
.
netcat
서버를 시작하는 몇 가지 방법은 다음과 같습니다 .
(나는 사용한다nmap
~의ncat
왜냐하면암소 비슷한 일종의 영양nc
2004년 이후 업데이트를 본 적이 없음)
local $ :|{ ncat -l 9999 --keep-open --allow localhost |
local > PS1='ncat $ ' PS2='ncat > ' dash +m -i 2>&1
local > } 1<>/dev/fd/0
[1] + Running : | { ncat -l 9999 --keep-open --allow localhost | PS1='ncat $ ' PS2='ncat > ' dash +m -i 2>&1; } 1<>/dev/fd/0
나는 :|
마지막 파이프를 빌렸습니다. dash
거기에 쓰고 ncat
읽습니다. :
물론 null 명령에는 필요하지 않기 때문입니다. 때로는 그것보다 더 쉽습니다 mkfifo
.
어쨌든 요점은 ncat
작성된 모든 내용이 stdin 으로 파이프 dash
되고 dash
작성된 모든 내용이 stdin 으로 파이프된다는 것입니다 ncat
. 알아요, 그렇지는 않지만 bash
고치겠습니다. 하지만 적어도 이 +m
옵션은 알고 있어야 합니다.
local $ ncat localhost 9999
ncat $ echo $0 $$
dash 31231
ncat $ ls -l /dev/fd/[012]
lr-x------ 1 mikeserv mikeserv 64 Dec 11 23:28 /dev/fd/0 -> pipe:[3563412]
l-wx------ 1 mikeserv mikeserv 64 Dec 11 23:28 /dev/fd/1 -> pipe:[3567682]
l-wx------ 1 mikeserv mikeserv 64 Dec 11 23:28 /dev/fd/2 -> pipe:[3567682]
ncat $ ^C
local $
+m
일반적 으로 기본적으로 대화형 셸이 열리도록 설정된 모니터링 되는 -m
작업 제어 셸이 -i
제어 터미널에서 데이터를 읽으려고 시도하고 SIGTTIN
기본적으로 자동으로 일시 중지되거나 그렇지 않은 경우(무시하거나 차단하려고 하는 경우)죽여.
[1] + Stopped(SIGTTIN) : | { ncat -l 9999 | dash -i 2>&1; } 1<>/dev/fd/0
하지만 여기에는 터미널이 없습니다. 출력에서 볼 수 있듯이 파이프일 뿐이 ls
므로 -m
모니터링이 불가능합니다.
bash
공교롭게도 초기 대화형 터미널 연결은 비활성화된 상태에서도 그다지 유연하지 않은 것 같습니다 readline
.
[1] + Stopped(SIGTTIN) : | { ncat -l 9999 | bash --noediting +m -i 2>&1 ; } 1<>/dev/fd/0
그래서 뭐 할까? 음, 의사 터미널이 필요합니다. 시뮬레이터에 있는 것과 똑같습니다.
local $ ls -l /dev/fd/[012]
lrwx------ 1 mikeserv mikeserv 64 Dec 11 23:30 /dev/fd/0 -> /dev/pts/0
lrwx------ 1 mikeserv mikeserv 64 Dec 11 23:30 /dev/fd/1 -> /dev/pts/0
lrwx------ 1 mikeserv mikeserv 64 Dec 11 23:30 /dev/fd/2 -> /dev/pts/0
/dev/ptmx
Linux 시스템의 마스터 장치에서 하나를 얻을 수 있습니다.tty
(먼저 그룹의 회원이 되고 싶지 않다면 사용자가 그룹의 회원이어야 할 수도 있습니다 chown
.). 만약 우리가<
open(2)
ptmx 장치는 다음과 같은 경우 새로운 의사 터미널을 생성합니다.unlockpt(3)
읽고 쓸 수 있는 새로운 장치 파일입니다.
얼마 전에 나는 쉘을 사용하여 이 작업을 수행하는 쉬운 방법이 없다는 것을 알았습니다.나는 그것을 위해 작은 C 프로그램을 작성했습니다.. 몇 가지 설명과 간단한 조립 지침을 확인할 수 있습니다.(실제로는 쉘 프롬프트에 복사/붙여넣기하면 됩니다)해당 링크에서 - 이것은 pts
제가 아래에서 사용하는 프로그램입니다.
local $ { 9>&- setsid -c -- bash <> "$({ pts &&
local > >&9 ncat -l 9999 -k --allow localhost
local > } <&9 &)" 2>&0 >&2 ; } 9<> /dev/ptmx
local $
bash
시작 이 있다회의 주최자의사 터미널에서 표준 출력을 잠금 해제하고 이름을 지정합니다. 리디렉션의 표준을 pts
대체합니다 . 하지만 모든 I/O는 다른 곳에(새로운 의사 터미널) 있고 유일한 링크는 포트 9999에서 시작된 서버에 있기 때문에 아무 일도 일어나지 않는 것 같습니다. 여기서는 대화형 스위치가 필요하지 않습니다. 자동으로 자체 Ltd.가 됩니다.<>
bash
ncat
-i
bash
local $ ncat localhost 9999
[mikeserv@desktop ~]$ echo hey
echo hey
hey
[mikeserv@desktop ~]$ ls -l /dev/fd/[012]
ls -l /dev/fd/[012]
lrwx------ 1 mikeserv mikeserv 64 Dec 12 00:27 /dev/fd/0 -> /dev/pts/4
lrwx------ 1 mikeserv mikeserv 64 Dec 12 00:27 /dev/fd/1 -> /dev/pts/4
lrwx------ 1 mikeserv mikeserv 64 Dec 12 00:27 /dev/fd/2 -> /dev/pts/4
[mikeserv@desktop ~]$ ^[[A^[[A
이제 거의 다 왔습니다. 따라서 우리는 확실히 소켓이 있는 bash
- 을 가지고 있지만 거기에 이상한 이중 에코가 있다는 것을 알 수 있으며 마지막 프롬프트에서 흥미로운 탈출은 실제로 ^위쪽 화살표 키를 누르는 것입니다. 여기서 문제는 두 가지 수준의 의사 터미널이 있다는 것입니다. 내 클라이언트가 실행 중인 의사 터미널은 서버가 실행 중인 의사 터미널과 동일하게 ncat
설정되어 있습니다 . stty echo
그리고 클라이언트 터미널은 라인 지향적이며 입력 개행당 한 번씩 출력을 플러시하고 stty echoctl
기본 설정에 따라 ctrl-char 이스케이프도 인쇄하므로 bash
^up 화살표 키는 전혀 수신되지 않고 재미있는 Little 이스케이프만 볼 수 있습니다.
좋아요 우리도 이 문제를 처리할 수 있습니다.
local $ ncatsh()(
local > ${2+":"} set localhost "${1:?ncatsh(): No port number provided!}"
local > stty=" stty -F'$(tty)'" || unset stty
local > trap " ${stty- ncat '${1##*\'*}' '${2##*\'*}' </dev/null} \
local > ${stty+$(for a in -g 'raw -echo isig intr "^A" quit "" susp ""'
local > do eval "$stty $a";done)}
local > trap - 0 1 2; exit" 0 1 2
local > ncat "$@"
local > )
이 함수는 표준 입력이 터미널(로컬 터미널)인지 확인하고 그렇지 않은 경우 입력을 client 에 전달합니다 ncat
. 하지만 trap
만약 그렇다면출구,끊다, 그리고방해하다신호는 종료 시 표준 터미널 상태를 다시 시작합니다. 이것도 좋은 일이니까.변화ncat
표준을 호출하기 전의 상태입니다.
로컬 에코가 비활성화되었습니다. 그렇지 않으면 로컬 터미널이 다음으로 설정됩니다.날것의모드 - 모든 키 누름이 ncat
즉시 서버로 전송됩니다. 실제로 모든 특수 로컬 모드 키가 비활성화됩니다.와는 별개로현지의정수- 대개CTRL+C
, 그러나 여기의 구성은 다음과 같습니다.CTRL+A
반대로 - 왜냐면CTRL+C
bash
서버에서 해석됩니다 .
다시 하고 싶지만 ls
^ 위쪽 화살표를 누르세요.RETURN
.
local $ ncatsh 9999
[mikeserv@desktop ~]$ ls -l /dev/fd/[012]
lrwx------ 1 mikeserv mikeserv 64 Dec 12 01:00 /dev/fd/0 -> /dev/pts/4
lrwx------ 1 mikeserv mikeserv 64 Dec 12 01:00 /dev/fd/1 -> /dev/pts/4
lrwx------ 1 mikeserv mikeserv 64 Dec 12 01:00 /dev/fd/2 -> /dev/pts/4
[mikeserv@desktop ~]$ ^C
[mikeserv@desktop ~]$ ^C
[mikeserv@desktop ~]$ ^C
[mikeserv@desktop ~]$
local $
누르면 로컬반향이 꺼지니까 거기는 안보이는데 눌렀어요CTRL+A
세션을 중단하고 모든 로컬 터미널 구성이 올바른 상태로 복원된 로컬 프롬프트로 돌아갑니다. 하지만 서버는 bash
여전히 거기에 있으며 ncatsh 9999
, 내가 선택하면 바로 다시 데려다 줄 것입니다.
답변2
작업을 단순화하려면 "netcat" 도구를 사용해 보십시오. 서버나 클라이언트로 사용될 수 있으며 임의의 데이터를 보내고 받을 수 있습니다.
그렇다면 낮은 수준의 물건을 다루는 데 신경 쓰지 마십시오.
#server listening on port 8000/tcp
$>netcat -l 8000
#client sending stuff to localhost 8000/tcp
$>netcat localhost 8000
blah
답변3
bash
가상 /dev/tcp/host/port
파일(원래 ksh 함수)은 다음과 같은 경우에만 사용할 수 있습니다.연결하다TCP 포트 소켓.
청취 소켓을 생성하고 그로부터 수용 소켓을 생성하는 등 더 많은 작업을 수행하려는 경우 리디렉션을 사용하여 수행할 수 없습니다.
zsh
zsh/net/tcp
모듈과 내장 기능을 통해 이를 지원합니다 ztcp
.
zmodload zsh/net/tcp
handle-connection() (
IFS= read -ru4 line || exit
print -r "Got: $line"
print -ru4 "Hello $line"
ztcp -c 4
)
ztcp -l -d 3 1234 # create a TCP listening socket on port 1234 on fd 3
while ztcp -ad4 3 # accept connection on fd 4
do handle-connection & exec 4>&-
done
바인딩할 주소나 청취 대기열의 크기를 지정할 수 없거나 한 방향만 끄거나 소켓 옵션을 설정할 수 없다는 점에서 여전히 제한적입니다. UDP 또는 SCTP도 수행하지 않습니다(할 수 있음). 명령을 사용하지만 Unix 도메인 소켓 인터페이스 zsocket
).
더 고급 기능 을 원하거나 zsh가 없는 경우 socat
.bash
handle_connection() {
IFS= read -r line &&
printf 'Hello %s\n' "$line"
}
export -f handle_connection
socat tcp-listen:1234,reuseaddr,fork 'exec:bash -c handle_connection'
가능성 은 socat
무궁무진합니다. 자세한 내용은 매뉴얼 페이지를 참조하세요.
예를 들어, 서버가 셸 세션을 생성하도록 하려면 다음을 수행하세요.
socat tcp-listen:1234,reuseaddr,fork exec:bash,pty,ctty,setsid,stderr,sane
클라이언트 측에서는 다음과 같이 연결할 수 있습니다.
socat -,raw,echo=0 tcp:host:1234
답변4
가장 쉬운 방법은 xinetd
다음과 같이 자신만의 서비스를 만드는 것입니다.
/etc/services
:
...
foo 500/tcp
...
/etc/xinetd.d/foo
:
service foo
{
disable = no
bind = 127.0.0.1
socket_type = stream
protocol = tcp
log_on_failure += USERID
server = /usr/local/lib/foo.sh
user = il
instances = UNLIMITED
wait = no
log_on_success =
}
/usr/local/lib/foo.sh
:
read ...
...
echo ...
따라서 쉘 스크립트는 각 클라이언트 연결에 대해 실행되고 stdin/stdout을 소켓에 직접 추가합니다.