# Nginx端口转发的坑

最近在配置Nginx转发端口的时候踩了个大坑，记录一下 需求是这样的，我们游戏服务器使用的wss协议，需要用nginx进行大量的端口转发，如wss://xxx.com/10000 转发到 ws://xxx.com:10000，后面的端口范围是10000到11000，我不

>最近在配置Nginx转发端口的时候踩了个大坑，记录一下

需求是这样的，我们游戏服务器使用的wss协议，需要用nginx进行大量的端口转发，如wss://xxx.com/10000 转发到 ws://xxx.com:10000，后面的端口范围是10000到11000，我不想写1000条这样的规则，于是我在网上找了这样一段代码：
```
location ~* ^/(?<port>\d+)$ {
    proxy_pass http://127.0.0.1:$port;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
    proxy_set_header Host $host;
}
```
咋一看，好像确实能用，就是把/port替换成:port。之后被同事发现了，惊呼我艹，这特么相当于在公网裸奔。服务器的安全组虽然设置了只对外开放10000到11000端口，但是这段代码，相当于在用户可以通过nginx的80或者443端口，间接访问到任意端口！当服务器的规模还小的时候，一切都正常，但是当用户量上去了，一定会被扫，一旦被扫到一些敏感端口，后果不堪设想。

如何解决这个问题，首先想到的是用if语句，但在Nginx社区中有一个说法"If Is Evil"（if是邪恶的），因为在某些复杂情况下if语句可能导致意外行为。所以我最终采取匹配数字的方式：
```
location ~* ^/(?<port>(20[0-9]\{3\}))$ {
    proxy_pass http://127.0.0.1:$port;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
    proxy_set_header Host $host;
}
```
意思是0到9这一区段数值重复3个，也就是10000-10999的端口能匹配上，这样子其它端口就匹配不上，或者：
```
location ~* ^/(?<port>2[0-1]\d\d\d)$ {
    proxy_pass http://127.0.0.1:$port;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
    proxy_set_header Host $host;
}
```