服务器原来配置了haproxy,因为对外只开放了80端口,没有开放22端口,所以haproxy配置了端口转发,规则如下(在/etc/haproxy/haproxy.cfg):

 

  1. #By http://blog.creke.net/
  2. global
  3. maxconn 5120
  4. chroot /usr/share/haproxy
  5. daemon
  6. quiet
  7. nbproc 2
  8. pidfile /usr/share/haproxy/haproxy.pid
  9. defaults
  10. option httplog
  11. option dontlognull
  12. timeout connect 5s
  13. timeout client 50s
  14. timeout server 20s
  15. listen http
  16. bind :80
  17. timeout client 1h
  18. tcp-request inspect-delay 2s
  19. acl is_http req_proto_http
  20. tcp-request content accept if is_http
  21. server server-http :8080
  22. backend ssh
  23. mode tcp
  24. timeout server 1h
  25. server server-ssh :22

意思是,绑定80端口,如果收到tcp连接请求,则延时2秒用于判断,如果是http协议,则转发到8080端口(webserver),否则,转发到22端口。

一、问题

这样配置后,基本问题不大,我们可以用过浏览器直接访问网址,也可以通过bitvise或者xshell指定80端口进行ssh连接。

但是,当我们使用linux进行连接时,会报错!刚开始连接的语句为:

 

ssh xxx@xxxxx 80

错误如下:

QQ图片20160128191859

 

它并没有把80自动识别为端口,而是默认连接22端口,于是我加了-p指定端口,如下:

 

ssh xxx@xxxxx -p 80

 

QQ图片20160128192113

这个时候,我们简单地看到ssh_exchange_identification错误,于是我搜索了一下,发现被告知是最大连接数或者是白名单黑名单的问题,于是我查了一遍最大连接数,/etc/hosts.allow ,/etc/hosts.deny,均没有发现特别的设置。

于是,继续使用-v打印详细的ssh连接信息:

QQ图片20160128192519

 

我们发现ssh连接会有Bad Request,这个明显是webserver的400回复啊,为了进一步确认,我在局域网内(局域网开放了8080端口,外网只开放80端口)ssh8080端口,结果和上面一样,如下图:

QQ图片20160128192446

 

这个时候可以确认问题所在了,就是使用linux终端直接ssh的时候,haproxy还是直接转发到了8080端口,意思是我们的转发规则并没有写好。

二、测试与改进haproxy规则

使用nc命令查看payload,利用payload来进行判断,从而进行转发,命令如下:

 

nc -l 8888|hexdump -C

我们先随便绑定一个8888端口,然后hexdump输出16进制信息,看看ssh与http请求有什么不一样的地方。输入上述命令后,会开始监听8888端口,于是我们可以对8888端口发送ssh和http请求:

ssh:直接在终端上面输入ssh localhost -p 8888即可

http:打开浏览器,输入网址localhost:8888

然后我们会有如下的结果:

QQ图片20160128193549

 

于是,我们可以对haproxy的转发规则进行修改,如下:

 

  1. #By http://blog.creke.net/
  2. global
  3. maxconn 5120
  4. chroot /usr/share/haproxy
  5. daemon
  6. quiet
  7. nbproc 2
  8. pidfile /usr/share/haproxy/haproxy.pid
  9. defaults
  10. option httplog
  11. option dontlognull
  12. timeout connect 5s
  13. timeout client 50s
  14. timeout server 20s
  15. listen http
  16. bind :80
  17. timeout client 1h
  18. tcp-request inspect-delay 2s
  19. #2016.1.28 siukwan改 G E T P O S P U T D E L etc
  20. acl is_http req.payload(0,3) -m bin 474554 504f53 505554 44454c
  21. # S S H
  22. acl is_ssh req.payload(0,3) -m bin 535348
  23. tcp-request content accept if is_http
  24. server server-http :8080
  25. backend ssh
  26. mode tcp
  27. timeout server 1h
  28. server server-ssh :22

最后需要kill haproxy进程,然后使用如下命令启动:

 

/usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg

 

使用终端直接指定80端口进行ssh连接,能够成功连接上!

 

https://blog.csdn.net/jmlikun/article/details/50605162