Feb
22
挑战:某Linux机器A有外网访问权限,但其上运行的ssh服务(22端口)仅对内网开放,希望通过外网的某Linux机器B进行RELAY,实现对机器A的ssh登录。特别地,只要能够进行ssh连接,就可以建立socks代理,实现内网其余机器的访问。
原理:(ssh服务器)A:22 <---- 连接 ~ 连接 ----> 监听B:10001 ~ 监听B:10002 <---- 连接(ssh客户端)
其中的 ~ 表示将两个连接/监听的socket的输入和输出分别连接起来。
简单实现(nc + shell):
1. 在机器B上运行
2. 在机器A上运行
3. 使用ssh客户端连接B:10001即可。
简单实现的主要问题是,一旦ssh客户端断开连接,部分/所有的nc会结束,无法再建立连接。所以需要改进:
1. 写一个死循环脚本来保证nc的运行,例如 for ((;;)); do nc localhost 22 <pipe | nc [B.ip] 10002 >;pipe; done
2. 将该脚本放入 /etc/rc.local ,保证每次开机后自动运行。
还有一个蛋疼的问题是,(在我的测试中)如果ssh客户端被强制断开连接(不是 $exit ),B上面监听10002端口的那个nc不一定会结束。虽然我特意安排了B机器的脚本管道前监听10002,管道后监听10001,希望能利用SIGPIPE来搞定,但是系统似乎抽风。所以还是需要一个机制来保证一旦某个nc结束了,另一个nc也会结束。可能还有一些其他更蛋疼的情况,无法一一列出来。
为了解决nc不结束的蛋疼情况,可以用脚本来实现:记录2个nc的PID,然后定时grep之。如果只剩下1个,就把另一个也kill掉。不过我没有采用这个方案,而是写了一个c程序来处理,pipe出两对fd,fork出两个child,把两对fd dup成两个child的stdin/stdout,child分别exec执行nc,然后wait之,当wait返回以后,就用kill向两个pid送个SIGTERM,结束。然后进入下一轮循环
代码如下(此代码用于B机器,A机器只要稍微修改下exec的参数就行了):
转载请注明出自 ,如是转载文则注明原出处,谢谢:)
RSS订阅地址: https://www.felix021.com/blog/feed.php 。
原理:(ssh服务器)A:22 <---- 连接 ~ 连接 ----> 监听B:10001 ~ 监听B:10002 <---- 连接(ssh客户端)
其中的 ~ 表示将两个连接/监听的socket的输入和输出分别连接起来。
简单实现(nc + shell):
1. 在机器B上运行
引用
mkfifo pipe
nc -l -p 10002 < pipe | nc -l -p 10001 > pipe
nc -l -p 10002 < pipe | nc -l -p 10001 > pipe
2. 在机器A上运行
引用
mkfifo pipe
nc localhost 22 < pipe | nc [B.ip] 10002 > pipe
nc localhost 22 < pipe | nc [B.ip] 10002 > pipe
3. 使用ssh客户端连接B:10001即可。
简单实现的主要问题是,一旦ssh客户端断开连接,部分/所有的nc会结束,无法再建立连接。所以需要改进:
1. 写一个死循环脚本来保证nc的运行,例如 for ((;;)); do nc localhost 22 <pipe | nc [B.ip] 10002 >;pipe; done
2. 将该脚本放入 /etc/rc.local ,保证每次开机后自动运行。
还有一个蛋疼的问题是,(在我的测试中)如果ssh客户端被强制断开连接(不是 $exit ),B上面监听10002端口的那个nc不一定会结束。虽然我特意安排了B机器的脚本管道前监听10002,管道后监听10001,希望能利用SIGPIPE来搞定,但是系统似乎抽风。所以还是需要一个机制来保证一旦某个nc结束了,另一个nc也会结束。可能还有一些其他更蛋疼的情况,无法一一列出来。
为了解决nc不结束的蛋疼情况,可以用脚本来实现:记录2个nc的PID,然后定时grep之。如果只剩下1个,就把另一个也kill掉。不过我没有采用这个方案,而是写了一个c程序来处理,pipe出两对fd,fork出两个child,把两对fd dup成两个child的stdin/stdout,child分别exec执行nc,然后wait之,当wait返回以后,就用kill向两个pid送个SIGTERM,结束。然后进入下一轮循环
代码如下(此代码用于B机器,A机器只要稍微修改下exec的参数就行了):
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <assert.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/wait.h>
void error(const char *fmt, ...)
{
perror("Infomation");
fprintf(stderr, " => ");
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
}
int main(int argc, char *argv[])
{
int fd_left[2], fd_right[2];
if (pipe(fd_left) < 0 ) {
perror("pipe left failed");
return 1;
}
if (pipe(fd_right) < 0 ) {
perror("pipe right failed");
return 1;
}
pid_t pid1 = fork();
if (pid1 < 0) {
perror("fork1");
return 1;
}
if (pid1 == 0) {
//child
if (dup2(fd_left[0], STDIN_FILENO) < 0) {
error("dup2@1@stdin");
}
if (dup2(fd_right[1], STDOUT_FILENO) < 0) {
error("dup2@1@stdout");
}
execlp("nc", "nc", "-l", "-p", "10001", NULL);
perror("execlp");
return 1;
}
fprintf(stderr, "pid1 = %d\n", pid1);
//parent
pid_t pid2 = fork();
if (pid2 < 0) {
perror("fork2");
return 1;
}
if (pid2 == 0) {
//child
if (dup2(fd_right[0], STDIN_FILENO) < 0) {
error("dup2@1@stdin");
}
if (dup2(fd_left[1], STDOUT_FILENO) < 0) {
error("dup2@1@stdout");
}
execlp("nc", "nc", "-l", "-p", "10002", NULL);
perror("execlp");
return 1;
}
fprintf(stderr, "pid2 = %d\n", pid2);
int status;
pid_t pid = wait(&status);
error("Process[%d] exits\n", pid);
kill(pid1, SIGTERM);
kill(pid2, SIGTERM);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <assert.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/wait.h>
void error(const char *fmt, ...)
{
perror("Infomation");
fprintf(stderr, " => ");
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
}
int main(int argc, char *argv[])
{
int fd_left[2], fd_right[2];
if (pipe(fd_left) < 0 ) {
perror("pipe left failed");
return 1;
}
if (pipe(fd_right) < 0 ) {
perror("pipe right failed");
return 1;
}
pid_t pid1 = fork();
if (pid1 < 0) {
perror("fork1");
return 1;
}
if (pid1 == 0) {
//child
if (dup2(fd_left[0], STDIN_FILENO) < 0) {
error("dup2@1@stdin");
}
if (dup2(fd_right[1], STDOUT_FILENO) < 0) {
error("dup2@1@stdout");
}
execlp("nc", "nc", "-l", "-p", "10001", NULL);
perror("execlp");
return 1;
}
fprintf(stderr, "pid1 = %d\n", pid1);
//parent
pid_t pid2 = fork();
if (pid2 < 0) {
perror("fork2");
return 1;
}
if (pid2 == 0) {
//child
if (dup2(fd_right[0], STDIN_FILENO) < 0) {
error("dup2@1@stdin");
}
if (dup2(fd_left[1], STDOUT_FILENO) < 0) {
error("dup2@1@stdout");
}
execlp("nc", "nc", "-l", "-p", "10002", NULL);
perror("execlp");
return 1;
}
fprintf(stderr, "pid2 = %d\n", pid2);
int status;
pid_t pid = wait(&status);
error("Process[%d] exits\n", pid);
kill(pid1, SIGTERM);
kill(pid2, SIGTERM);
return 0;
}
欢迎扫码关注:
转载请注明出自 ,如是转载文则注明原出处,谢谢:)
RSS订阅地址: https://www.felix021.com/blog/feed.php 。
Felix021
2012-2-23 15:32
这是一条隐藏评论或留言。您需要以合适的身份登入后才能看到。
Felix021
2012-2-23 13:47
这是一条隐藏评论或留言。您需要以合适的身份登入后才能看到。
miuc
2012-2-23 13:04
这是一条隐藏评论或留言。您需要以合适的身份登入后才能看到。
Felix021
2012-2-23 10:45
这是一条隐藏评论或留言。您需要以合适的身份登入后才能看到。
Magiclouds Magicloud
2012-2-22 12:40
这是一条隐藏评论或留言。您需要以合适的身份登入后才能看到。
Magiclouds Magicloud
2012-2-22 12:34
这是一条隐藏评论或留言。您需要以合适的身份登入后才能看到。
分页: 1/1 1