Quantcast
Channel: 容器云计算,Devops,DBA,网络安全。
Viewing all articles
Browse latest Browse all 780

使用Nginx代理转发TCP/UDP协议

$
0
0

环境

  • OS: Centos6-x86_64

  • Nginx: 1.12.1


编译安装Nginx

从1.9.0开始,nginx就支持对TCP的转发,而到了1.9.13时,UDP转发也支持了。提供此功能的模块为ngx_stream_core。不过Nginx默认没有开启此模块,所以需要手动安装。

cd /usr/local/src
wget http://nginx.org/download/nginx-1.12.1.tar.gz
tar zxf nginx-1.12.1.tar.gz
cd nginx-1.12.1
./configure --prefix=/usr/local/nginx --with-stream --without-http
make && make install

Note:由于是传输层转发,本着最小化原则,就关闭了http功能。


配置Nginx

TCP转发

目标:通过3000端口访问本机Mysql(其中mysql使用yum安装,默认配置文件)

/usr/local/nginx/conf/nginx.conf配置如下:


user  nobody;

worker_processes  auto;

#error_log  logs/error.log;

#error_log  logs/error.log  notice;

#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {

    use epoll;

    worker_connections  1024;

}


stream {

    server {

        listen 3000;

        proxy_pass 127.0.0.1:3306;


    # 也支持socket

    # proxy_pass unix:/var/lib/mysql/mysql.socket;

    }

}


首先,先通过3306端口访问mysql:




然后,启动Nginx:




最后使用3000端口访问mysql:



UDP转发

目标: 发送UDP数据到3000端口,3001端口可以接收


/usr/local/nginx/conf/nginx.conf配置如下:


user  nobody;

worker_processes  auto;


#error_log  logs/error.log;

#error_log  logs/error.log  notice;

#error_log  logs/error.log  info;


#pid        logs/nginx.pid;


events {

    use epoll;

    worker_connections  1024;

}



stream {

    server {

        listen 3000 udp;

        proxy_pass 127.0.0.1:3001;


    }

}

这里写一个my_socket_server.py侦听在3001端口,用于接收UDP数据:


# coding=utf-8


import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

sock.bind(('127.0.0.1', 3001))

print ('start server on [%s]:%s' % ('127.0.0.1', 3001))

while True:

    data, addr = sock.recvfrom(1024)

    print ('Received from %s:%s' % (addr,data))

    sock.sendto(b'Hello, %s!' % data, addr)


再写一个my_socket_client.py用于向Nginx侦听的3000端口发送数据:


# coding=utf-8


import socket

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

while True:

    data = raw_input('Input msg: ')

    if len(data) == 0:

        continue

    s.sendto(data.encode(), ('127.0.0.1', 3000))

    print (s.recv(1024).decode('utf-8'))

同时运行两个脚本,在client端发送数据:




4.gif

UDP转发遇到的一个坑

修改下client脚本,改为连续发送2000个数据包:

# coding=utf-8


import socket


s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)


for data in range(2000):

    s.sendto(str(data).encode(), ('127.0.0.1', 3000))

    print (s.recv(1024).decode('utf-8'))


然后运行client脚本,发现经常会遇到如下情况:

image.png

由图可知只成功了511个。

查看文档得知listen指令有个backlog参数,此参数在Linux系统中默认为511:

 

悲剧的是backlog参数和udp参数不能同时使用。如果哪位朋友有好的解决办法,请赐教!!!!

“UDP转发遇到的一个坑”部分遇到的问题,client成功的连续发送了511条UDP协议与listen指令的backlog参数在Linux平台的默认值一致只是巧合,其实与listen的backlog参数没有关系,该参数与udp是不兼容的。然后查看error.log会发现,问题是“1024 worker_connections are not enough”,也就是说工作进程中并发连接数达到上限(1024)了。然后问题是为什么nginx给被代理服务器转发UDP协议,会一直占用连接呢?前面引用的链接中给出了解答,是因为我们没有设置“proxy_responses"指令,因此nginx默认是不限制来自被代理服务器的响应数据报数量的。因此,使用py脚本连续给nginx发送UDP协议时,nginx在收到第一个UDP协议时,会与被代理的服务器(python_server脚本)建立连接,然后得到来自被代理服务器的响应数据报,同时也收到了第二个UDP协议,又与被代理服务器建立连接,然后得到了第二个UDP协议对应的响应数据报...由于没有限制”proxy_responses",导致每一次为转发UDP协议而与被代理服务器建立的连接都不认为会话结束,都没有断开,因此很快会话数量就达到了配置的上限(worker_connections)。我们服务器每次会回复一条UDP协议,因此增加一条指令"proxy_responses 1;"就可以了。


作者:胖宝宝王
链接:https://www.jianshu.com/p/244386221cc5
 



Viewing all articles
Browse latest Browse all 780

Trending Articles


Vimeo 10.7.1 by Vimeo.com, Inc.


UPDATE SC IDOL: TWO BECOME ONE


KASAMBAHAY BILL IN THE HOUSE


Girasoles para colorear


Presence Quotes – Positive Quotes


EASY COME, EASY GO


Love with Heart Breaking Quotes


Re:Mutton Pies (lleechef)


Ka longiing longsem kaba skhem bad kaba khlain ka pynlong kein ia ka...


Vimeo 10.7.0 by Vimeo.com, Inc.


FORECLOSURE OF REAL ESTATE MORTGAGE


FORTUITOUS EVENT


Pokemon para colorear


Sapos para colorear


Smile Quotes


Letting Go Quotes


Love Song lyrics that marks your Heart


RE: Mutton Pies (frankie241)


Hato lada ym dei namar ka jingpyrshah jong U JJM Nichols Roy (Bah Joy) ngin...


Long Distance Relationship Tagalog Love Quotes