如何将 DNS 重定向到不同的端口

译者:

域的 DNS 解析必须映射到 IP:port(s),而不仅仅是 IP

例如,

sub1.example.com 192.0.2.4:4567
sub2.example.com 192.0.2.4:5678

我可以修改 DNS 记录。


我拥有“ Arboristal.com”域名,也拥有 Arboristal.com 上的所有子域名,比如 lg.arboristal 或者 ft.Arboristal.com。

在我的 DNS 设置下,Arboristal.com 被设置为访问我们目前托管我们网站的主机。

我家里有三台服务器都在一个公共 IP 地址下运行

我还有三个子域名的 Arboristal.com 指向我的 IP 地址。

三个服务器中的每一个都在各自的端口上运行(25565、25566、25567)

我希望每个子域指向我的 IP 地址上的每个开放端口。

不幸的是,当您尝试使用其中一个子域连接到这些服务器时,它只连接到您键入端口的服务器。

我的情况:

三个服务器,每个运行在不同的端口

  • Minecraft 服务器1(25565)

  • Minecraft 服务器2(25566)

  • Minecraft 服务器3(25567)

我有三个子域名运行在我的 DNS 提供商(webs.com)

  • Mc.arboristal.com

  • Tekkit.arboristal.com

  • Pvp.artboristal.com

当您使用 Minecraft 连接到其中一个时,它会自动通过端口25565连接,这意味着无论您尝试连接到什么 URL,它总是连接到我的 IP 端口25565。正在连接“我的世界”服务器一号。你可以手动输入端口,但我宁愿保持这一良好的外观和专业尽可能。

那么,现在你知道了我的情况,有没有什么可能的方法,我可以让 mc.arboristal.com , tekkit.arboristal.com 和 pvp.arboristal.com 都到我的 IP 地址在不同的端口,而不必指定每个端口在提供的 URL 连接到用户端?

我可以添加 MX,A (使用这一个连接到服务器) ,CNAME 和 TXT 记录到 DNS 设置

我也可以添加名称服务器到 DNS 设置,如果我需要使用第三方作为我的 DNS 提供商。(如有需要,我愿意做)

如果需要在192.168.0.1配置任何东西,我也可以完全访问我的路由器。

我只是在上周才知道互联网到底是如何运作的,所以我不确定这里是否有任何事情是真正可能的。我也可能没有关于互联网实际运作的正确信息。请原谅我对互联网的任何假设。

176928 次浏览

You can use SRV records:

_service._proto.name. TTL class SRV priority weight port target.

Service: the symbolic name of the desired service.

Proto: the transport protocol of the desired service; this is usually either TCP or UDP.

Name: the domain name for which this record is valid, ending in a dot.

TTL: standard DNS time to live field.

Class: standard DNS class field (this is always IN).

Priority: the priority of the target host, lower value means more preferred.

Weight: A relative weight for records with the same priority.

Port: the TCP or UDP port on which the service is to be found.

Target: the canonical hostname of the machine providing the service, ending in a dot.

Example:

_sip._tcp.example.com. 86400 IN SRV 0 5 5060 sipserver.example.com.

So what I think you're looking for is to add something like this to your DNS hosts file:

_minecraft._tcp.arboristal.com. 86400 IN SRV 10 40 25565 mc.arboristal.com.
_minecraft._tcp.arboristal.com. 86400 IN SRV 10 30 25566 tekkit.arboristal.com.
_minecraft._tcp.arboristal.com. 86400 IN SRV 10 30 25567 pvp.arboristal.com.

(Minecraft supports SRV records, as of 1.3.1, with the service name minecraft)

On a side note, I highly recommend you go with a hosting company rather than hosting the servers yourself. It's just asking for trouble with your home connection (DDoS and Bandwidth/Connection Speed), but it's up to you.

(It's been a while since I did this stuff. Please don't blindly assume that all the details below are correct. But I hope I'm not too embarrassingly wrong. :))


As the previous answer stated, the Minecraft client (as of 1.3.1) supports SRV record lookup using the service name _minecraft and the protocol name _tcp, which means that if your zone file looks like this...

arboristal.com.                 86400 IN A   <your IP address>
_minecraft._tcp.arboristal.com. 86400 IN SRV 10 20 25565 arboristal.com.
_minecraft._tcp.arboristal.com. 86400 IN SRV 10 40 25566 arboristal.com.
_minecraft._tcp.arboristal.com. 86400 IN SRV 10 40 25567 arboristal.com.

...then Minecraft clients who perform SRV record lookup as hinted in the changelog will use ports 25566 and 25567 with preference (40% of the time each) over port 25565 (20% of the time). We can assume that Minecraft clients who do not find and respect these SRV records will use port 25565 as usual.


However, I would argue that it would actually be more "clean and professional" to do it using a load balancer such as Nginx. (I pick Nginx just because I've used it before. I'm not claiming it's uniquely suited to this task. It might even be a bad choice for some reason.) Then you don't have to mess with your DNS, and you can use the same approach to load-balance any service, not just ones like Minecraft which happen to have done the hard client-side work to look up and respect SRV records. To do it the Nginx way, you'd run Nginx on the arboristal.com machine with something like the following in /etc/nginx/sites-enabled/arboristal.com:

upstream minecraft_servers {
ip_hash;
server 127.0.0.1:25566 weight=1;
server 127.0.0.1:25567 weight=1;
server 127.0.0.1:25568 weight=1;
}
server {
listen 25565;
proxy_pass minecraft_servers;
}

Here we are controlling the load-balancing ourselves on the server side (via Nginx), so we no longer need to worry that badly behaved clients might prefer port 25565 to the other two ports. In fact, now all clients will talk to arboristal.com:25565! But the listener on that port is no longer a Minecraft server; it's Nginx, secretly proxying all the traffic onto three other ports on the same machine.

We load-balance based on a hash of the client's IP address (ip_hash), so that if a client disconnects and then reconnects later, there's a good chance that it'll get reconnected to the same Minecraft server it had before. (I don't know how much this matters to Minecraft, or how SRV-enabled clients are programmed to deal with this aspect.)

Notice that we used to run a Minecraft server on port 25565; I've moved it to port 25568 so that we can use port 25565 for the load-balancer.

A possible disadvantage of the Nginx method is that it makes Nginx a bottleneck in your system. If Nginx goes down, then all three servers become unreachable. If some part of your system can't keep up with the volume of traffic on that single port, 25565, all three servers become flaky. And not to mention, Nginx is a big new dependency in your ecosystem. Maybe you don't want to introduce yet another massive piece of software with a complicated config language and a huge attack surface. I can respect that.

A possible advantage of the Nginx method is... that it makes Nginx a bottleneck in your system! You can apply global policies via Nginx, such as rejecting packets above a certain size, or responding with a static web page to HTTP connections on port 80. You can also firewall off ports 25566, 25567, and 25568 from the Internet, since now they should be talked to only by Nginx over the loopback interface. This reduces your attack surface somewhat.

Nginx also makes it easier to add new Minecraft servers to your backend; now you can just add a server line to your config and service nginx reload. Using the old port-based approach, you'd have to add a new SRV record with your DNS provider (and it could take up to 86400 seconds for clients to notice the change) and then also remember to edit your firewall (e.g. /etc/iptables.rules) to permit external traffic over that new port.

Nginx also frees you from having to think about DNS TTLs when making ops changes. Suppose you decide to split up your three Minecraft servers onto three different physical machines with different IP addresses. Using Nginx, you can do that completely via config changes to your server lines, and you can keep those new machines inside your firewall (connected only to Nginx over a private interface), and the changes will take effect immediately, by definition. Whereas, using SRV records, you'll have to rewrite your zone file to something like this...

arboristal.com.                 86400 IN CNAME mc1.arboristal.com.
mc1.arboristal.com.             86400 IN A   <a new machine's IP address>
mc2.arboristal.com.             86400 IN A   <a new machine's IP address>
mc3.arboristal.com.             86400 IN A   <a new machine's IP address>
_minecraft._tcp.arboristal.com. 86400 IN SRV 10 20 25565 mc1.arboristal.com.
_minecraft._tcp.arboristal.com. 86400 IN SRV 10 40 25565 mc2.arboristal.com.
_minecraft._tcp.arboristal.com. 86400 IN SRV 10 40 25565 mc3.arboristal.com.

...and you'll have to leave all three new machines poking outside your firewall so that they can receive connections from the Internet. And you'll have to wait up to 86400 seconds for your clients to notice the change, which could affect the complexity of your rollout plan. And if you were running any other services (such as an HTTP server) on arboristal.com, now you have to move them to the mc1.arboristal.com machine because of how I did that CNAME. I did that only for the benefit of those hypothetical Minecraft clients who don't respect SRV records and will still be trying to connect to arboristal.com:25565.


So, I think both ways (SRV records and Nginx load-balancing) are reasonable, and your choice will depend on your personal preferences. I caricature the options as:

  • SRV records: "I just need it to work. I don't want complexity. And I know and trust my DNS provider."
  • Nginx: "I foresee arboristal.com taking over the world, or at least moving to a bigger machine someday. I'm not scared of learning a new tool. What's a zone file?"

Possible solutions:

  1. Use nginx on the server as a proxy that will listen to port A and multiplex to port B or C.

  2. If you use AWS you can use the load balancer to redirect the request to specific port based on the host.

Since I had troubles understanding this post here is a simple explanation for people like me. It is useful if:

  • You DO NOT need Load Balacing.
  • You DO NOT want to use nginx to do port forwarding.
  • You DO want to do PORT FORWARDING according to specific subdomains using SRV record.

Then here is what you need to do:

SRV records:

_minecraft._tcp.1.12          IN SRV    1 100 25567 1.12.<your-domain-name.com>.
_minecraft._tcp.1.13          IN SRV    1 100 25566 1.13.<your-domain-name.com>.

(I did not need a srv record for 1.14 since my 1.14 minecraft server was already on the 25565 port which is the default port of minecraft.)

And the A records:

1.12                          IN A      <your server IP>
1.13                          IN A      <your server IP>
1.14                          IN A      <your server IP>

Use SRV record. If you are using freenom go to cloudflare.com and connect your freenom server to cloudflare (freenom doesn't support srv records) use _minecraft as service tcp as protocol and your ip as target, priority - 0, weight - 0 and port - the port you want to use.(i know this because i was in the same situation) Do the same for any domain provider. (sorry if i made spell mistakes)

Edit: Just realized that most of the things I typed didn't make any sense.