ngrok反向隧道

前情提要:小明与小白各有一台主机,两台主机在同一内网,小明想直接通过内网ssh到小白的主机上。但是小白的ip地址会不断的变化,而小明不想每次都要麻烦小白查看ip。于是小明催生了一个想法:写个脚本在自己的主机运行输出小白的ip。

01 获取本机ip地址

> cat ip-server.c

#include  <stdio.h>
#include  <sys/socket.h>
#include  <unistd.h>
#include  <sys/types.h>
#include  <netinet/in.h>
#include  <stdlib.h>
#include  <time.h>
#include  <string.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <arpa/inet.h>

#define  SERVER_PORT 20000  //  define the defualt connect port id
#define  LENGTH_OF_LISTEN_QUEUE 10  // length of listen queue in server
#define  BUFFER_SIZE 255 

unsigned long getNumIP(char* dev){//eth0
    int fd;
    struct ifreq ifr;
    fd = socket(AF_INET, SOCK_DGRAM, 0);
    /* I want to get an IPv4 IP address */
    ifr.ifr_addr.sa_family = AF_INET;
    /* I want IP address attached to "eth0" */
    strncpy(ifr.ifr_name, dev, IFNAMSIZ-1);
    int rtn=ioctl(fd, SIOCGIFADDR, &ifr);
    close(fd);
    if(rtn==-1) return rtn;
    /* display result */
    unsigned long numIP=((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
    return numIP;
}
int main(int argc, char** argv)
{
       int  servfd,clifd;
       struct  sockaddr_in servaddr,cliaddr;

       if  ((servfd  =  socket(AF_INET,SOCK_STREAM, 0 ))  <   0 )
         {
              printf( " create socket error!\n " );
              exit( 1 );
       } 

       bzero( & servaddr, sizeof (servaddr));

       servaddr.sin_family  =  AF_INET;
       servaddr.sin_port  =  htons(SERVER_PORT);
       servaddr.sin_addr.s_addr  =  htons(INADDR_ANY);

       if  (bind(servfd,( struct  sockaddr * ) & servaddr, sizeof (servaddr)) < 0 )
         {
              printf( " bind to port %d failure!\n " ,SERVER_PORT);
              exit( 1 );
       } 

        if  (listen(servfd,LENGTH_OF_LISTEN_QUEUE)  <   0 )
         {
              printf( " call listen failure!\n " );
              exit( 1 );
       } 

        while  ( 1 )
         { // server loop will nerver exit unless any body kill the process 

              char  buf[BUFFER_SIZE];
              long  timestamp;
              socklen_t length  =   sizeof (cliaddr);
              clifd  =  accept(servfd,( struct  sockaddr * ) & cliaddr, & length);

               if  (clifd  <   0 )
                {
                     printf( " error comes when call accept!\n " );
                     break ;
              } 

               // inet_ntop(INET_ADDRSTRLEN,cliaddr.sin_addr,buf,BUFFER_SIZE);
        //////////
        unsigned long numIP=getNumIP("ppp0");
        if(numIP==-1)//-1 error
        numIP=getNumIP("eth0");
         //printf("eth0:%lld\n",numIP);
        if(numIP==-1) numIP=getNumIP("wlan0");
         if(numIP==-1) numIP=0;
         struct in_addr iaddr;
         iaddr.s_addr=numIP;
         char* ip = inet_ntoa(iaddr);
        ////////
         strcpy(buf, ip );
         send(clifd,buf,strlen(buf), 0 );
         close(clifd);
        } // exit 

        close(servfd);
        return   0 ;
}

编译

> gcc ip-server.c -o ip-server

02 启动ngrok客户端

这里使用的是1.7版本,官方的2.0及之后非开源。

> cat start_ngrok.sh

#可以加入开机自启动脚本,如/etc/rc.local中
PRE=$HOME/bin/ngrok
NGROK_DIR=$PRE/ngrok1.7
$PRE/ip-server &
$NGROK_DIR/ngrok -log=stdout -config=$NGROK_DIR/ngrok.cfg -subdomain theUniqName 20000 > /dev/null 2>&1 &

其中ngrok.cfg中指定如下的内容:

server_addr: "xxxHostName:4443"

trust_host_root_certs: false

启动ngrok后,服务器xxxHostName上会开通一个子域名theUniqName,通过访问theUniqName.xxxHostName:80可以获取到ngrok客户端机器上的20000端口的内容。

在不添加-subdomain参数时服务端会选择一个未使用的端口,建立到你的本地的隧道。每次你重新建立隧道时给你分配的端口很可能不同。

另外还可以使用sunny博客博主提供的ngrok服务(www.ngrok.cc),用户注册后可以创建固定端口的隧道,并分配一个clientID,ngrok启动时指定这个clientID即可。

03 测试使用

在其他机器上通过curl来获取(因为ip-server程序中仅仅输出一行ip地址,而没有http头部信息,所以curl会检测出来并直接输出原内容)

> curl 隧道地址

另外,随手附上终止ngrok程序的脚本(ngrok在连接不到服务器时可能会不断尝试连接而不是自行退出)

> cat stop.sh

pid_1=$(ps ax|grep [i]p-server|awk '{print $1}')
pid_2=$(ps ax|grep [n]grok1.7/ngrok|awk '{print $1}')
if [ -z $pid_1 ];then
    echo 'ip_server not running'
else
    kill $pid_1
fi
if [ -z $pid_2 ];then
        echo 'ngrok not running'
else
        kill -9 $pid_2
fi
echo 'stopped ip-server and ngrok!'

04 END

反向隧道通常用来打通内网主机与公网主机的连接,可以方便web开发等。那么它与ssh反向隧道相比有什么优势呢?除了可以创建子域名的方式比较方便外,暂时也不太清楚,但是比ssh功能上要纯粹的多。

ngrok反向隧道--获取内网IP的更多相关文章

  1. 通过js获取内网ip和外网ip的简单方法 ...

    今天遇到了一个需求,需要获取用户当前的内网ip, 找了半天终于找到了方法,遂将找到的方法记录下来,留给需要的人. 1,获取内网ip function getIP(callback) { let rec ...

  2. xss实现获取内网ip

    前提得浏览器支持webRTC,测试的时候google浏览器测试成功,火狐浏览器不支持webRTC, 再在xss平台直接复制如下js代码: function form_ip(ip,port){ var ...

  3. JAVA 优先获取外网Ip,再获取内网Ip

    1.获取内网Ip private String getLocalhostIp(){ String hostAddress = ""; try { InetAddress addre ...

  4. Python获取内网IP

    Python 获取本机内网IP 本文记录使用Python获取本机IP的两种方法. 通过hostname来获取本机IP import socket print(socket.gethostbyname( ...

  5. (转)js获取内网ip地址,操作系统,浏览器版本等信息

    这次呢,说一下使用js获取用户电脑的ip信息,刚开始只是想获取用户ip,后来就顺带着获取了操作系统和浏览器信息. 先说下获取用户ip地址,包括像ipv4,ipv6,掩码等内容,但是大部分都要根据浏览器 ...

  6. 获取本机外网ip和内网ip

    获取本机外网ip //获取本机的公网IP public static string GetIP() { string tempip = ""; try { WebRequest r ...

  7. js获取设备内网ip

    可以直接使用,不需要导入其他配置 看代码 1 <script> 2 //获取内网ip 3 var RTCPeerConnection = window.RTCPeerConnection ...

  8. 根据Request获取客户端IP 内网IP及外网IP

    在JSP里,获取客户端的IP地址的方法是:request.getRemoteAddr() ,这种方法在大部分情况下都是有效的.但是在通过了Apache,Squid等反向代理软件就不能获取到客户端的真实 ...

  9. C#获取内网和外网IP

    写了个小客户端,里面用到了获取内网和外网的IP地址,代码如下: // InnerIP var ipHost = Dns.Resolve(Dns.GetHostName()); ]; innerIP = ...

随机推荐

  1. SpringMVC之HandlerMapping源码剖析(一)

    学习一种知识,我喜欢看看源码是怎么进行它们类之间的关系以及方法的调用,是怎么实现的.这样我才感觉踏实. 既然现在谈到HandlerMapping,我们先知道HandlerMapping的作用:Hand ...

  2. SQLite Expert Professional 3查看SQLite数据

    通常在android进行SQLite数据库的处理查看很不方便,于是自己下载了一个SQLite Expert Professional 3可视化工具用来进行查询数据,由于时间问题就不多说了,直接讲使用方 ...

  3. 怎样给div增加resize事件

    当浏览器窗口被调整到一个新的高度或宽度时,就会触发resize事件,这个事件在window上面触发,那么如何给div元素增加resize事件,监听div的高度或宽度的改变呢? 先来回答另一个问题,监听 ...

  4. 第三方开源库和jar包的区别

    jar包和第三方开源库的根本区别在于,开源库的功能比jar包功能更强大,通过引入库项目可以访问java文件以及该开源库项目下的资源文件,例如图片,layout等文件 jar包中只能放class文件 引 ...

  5. Express 4 handlebars 不使用layout写法

    Express 4 handlebars 不使用layout写法 Express node nodejs handlebars layout 最近刚开始学习使用nodejs. 使用express搭建了 ...

  6. linux基本知识

    1.默认不写端口号就是80端口   127.0.0.1.localhost都代表本机 2.linux下的用户管理: id:可以查看当前用户whoami:查看当前的用户who:看当前已经登录的用户w:也 ...

  7. 从零自学Hadoop系列索引

    本文版权归mephisto和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作. 文章是哥(mephisto)写的,SourceLink 从零自学Hadoop(01):认识Hadoop ...

  8. ubuntu下修改键位

    尴尬的背景: 服役5年的笔记本,最近键盘失灵,部分键位彻底失去响应.最蛋疼的是左右方向键都不能用了 ○| ̄|_ 解决方案是,通过xmodmap命令,用其他相对鸡肋些的键位替代方向键. 1 查看各个键位 ...

  9. kali linux之窥看女神上网隐私(ettercap+wireshark+zenmap +dsniff)

    作者:小波 http://www.cnblogs.com/xiaobo-Linux/ 无聊就玩了玩,不要干一些坏事哟~~网上也有一些文章关于kali linux的,就实战了一番.kali是用的debi ...

  10. windows中,端口查看&关闭进程及Kill使用

    测试过程中遇到的问题,杂记一: 1.netstat -ano | findstr "8001"    查看端口8001被哪个进程占用:由下图可以看出,被进程为3736的占用 2.查 ...