Moonlight Game Streaming Without Public IP, Using frp for Remote Gaming (with Video)
Due to certain circumstances, I have recently been using mobile data for my internet connection. When I had a broadband connection, I used to wake up my desktop computer using wakeOnLan on my Raspberry Pi. This allowed me to secretly connect to my desktop computer and play games remotely while at work (usually Final Fantasy 14 fishing). However, since my mobile network doesn’t provide a public IP address, I was curious to see how well game streaming using frp tunneling would work. So, I decided to give it a try…(English version Translated by GPT-3.5, 返回中文)
First, let me clarify a few things
- The selected bitrate in Moonlight should not exceed the maximum bandwidth of the server or the router, otherwise there will be significant lag.
- My server has a bandwidth of 5 Mbps, which seems to be able to handle streaming at 720p quality. However, games with a lot of motion may appear blurry (as seen in Horizon Zero Dawn).
- My desktop computer is connected to the network using 5G (not related to the 5G frequency band used by routers), and I am using an iPad for gaming through the frp tunnel provided by Alibaba Cloud.
- Why didn’t I choose to use “Peanut Shell”? I prefer to experiment with things that interest me.
- This article is just a record of my personal experiment. Although I also use remote game streaming for games like Onmyoji in my daily life, you may find this article more professional and dedicated to streaming A Comprehensive Guide to PC Game Streaming — Moonlight.
What I used
I used a cloud server with a bandwidth of at least 4 Mbps, preferably located in China (international connections can be slow). In my case, I used Alibaba Cloud.
Installing frps on the server
Download from GitHub:
frp_0.31.1_linux_amd64.tar.gz - for running on a Linux server
frp_0.31.1_windows_amd64.zip - for running on Windows
Installing frp for port forwarding
Installing frp is pretty simple, much simpler than ngrok.
First, download the Linux package and copy it to the server
I’ll be using /usr/local/frps
. After downloading the package, use the following command to extract it:
1 | tar -zxvf frp_0.31.1_linux_amd64.tar.gz |
This will extract the necessary files, and we’re only interested in frps
and frps.ini
. The other files are not needed.
Next, modify the frps.ini
file as follows
Nvidia Game Stream requires the following ports to be exposed:
1 | [common] |
So, my frps.ini
configuration is as follows:
1 | [common] |
The
bind_port
specified above is the communication port between the client and the server. This port must be open. Thebind_ip
specifies the IP address to listen on, and setting it to0.0.0.0
means it will listen on all network interfaces. If you have multiple public IP addresses on the server, you can also specify a particular IP address so that only that IP address’s9200
port can communicate with the server, and other public IP addresses won’t be able to communicate with the9200
port. This port must be opened, otherwise thefrpc
client won’t be able to connect to thefrps
server.The
allow_ports
specifies the communication ports forfrpc
specified in the configuration file below. Theseremote_port
s defined in the configuration file must be allowed here. If you want to access these ports from outside the server, you need to open them.
Finally, start frps. If you are using Alibaba Cloud, don’t forget to add port 9200
to the security group.
1 | ./frps -c ./frps.ini |
For setting up as a service, please refer to the relevant documentation.
Testing the connection via telnet
1 | telnet <frps_server_ip> 47984 |
If you can connect successfully, then the frp tunnel is working.
Setting up frp on the local machine
Download frp_0.31.1_windows_amd64.zip
You’ll find a similar file list as before. I just took the frpc.exe
and frpc.ini
files from the zip archive.
Modify the configuration file
1 | [common] |
Each section name, such as [nvidia-stream-tcp-1]
, must be unique.
The above configuration is explained as follows:
[nvidia-stream-udp-6]
can be interpreted as an ID with uniqueness.type = udp
specifies the communication protocol type, which can be TCP, UDP, or http.local_ip = 127.0.0.1
specifies the IP that can be accessed on the client.local_port = 48010
specifies the port that can be accessed on the client.remote_port = 48010
specifies the port to access the server (the public cloud server in this case).
For example, if you have a public cloud server with IP 64.64.1.222
named “PublicHost” and another company server with IP 10.1.1.100
named “InnerHost”, which cannot be accessed from the internet but can access the internet, and you also have another server at your company with IP 192.168.1.2
named “PrivateHost”, which can only communicate with InnerHost and has all ports open, and PrivateHost cannot access the internet. PrivateHost is deployed with a database on port 3306
, and you want to access this port on PrivateHost from the PublicHost’s port 13306
because PrivateHost can only communicate with InnerHost, and InnerHost can access the internet. In this case, you can install the Frpc client on InnerHost with the following complete configuration:
1 | [common] |
This allows you to access the PrivateHost’s database from the internet through PublicHost’s port 13306
.
Run frpc.exe
To run frp client:
1 | .\frpc.exe -c .\frpc.ini |
With this, the frpc setup is complete. To test if the tunneling is working, you can use telnet
for TCP or use dig
to check if the DNS is functioning properly (as suggested by the frp author).
Checking if the ports are open
First, change all type = udp
configurations in the frpc.ini
file to local_ip = 223.5.5.5
and local_port = 53
. Then restart frpc. Use dig
from any remote server to check if the ports are open. The following example shows the results:
1 | dig @<frps_server_ip> -p 53 google.com |
Make sure to change the configurations back after testing.
Starting the Game Streaming
Install Moonlight and start playing Horizon Zero Dawn
Here, I’ll be using my iPad. I turned off Wi-Fi and used mobile data (or a mobile hotspot, but in this case, I just wanted to demonstrate that I’m not using a local network).
Add the server’s IP
Since we have set up the port forwarding, and the forwarded ports are the same as the GameStream’s original ports, when Moonlight accesses these ports on the server, it is actually accessing these ports on our local machine.
If everything goes well, you should see a locked computer.
If not, you can try the following steps:
- Change the configuration back to DNS (
local_ip = 223.5.5.5
andlocal_port = 53
), then usedig
to confirm. - Test the streaming on the same local network as the PC to ensure that the Nvidia GameStream service is working properly. Check the firewall settings if necessary.
Connecting to the Desktop Computer
Click on the locked computer to initiate the pair request. The iPad will display the following:
The PC side will show a pop-up message in the bottom right corner:
Enter the same number on the computer, and the pairing process will be completed. (Pairing needs to be done only once)
Playing Forza Horizon 4 (with Gameplay Video)
Don’t forget to adjust the parameters; otherwise, there may be lag (because my server’s maximum bandwidth is 5 Mbps).
Here is a gameplay video. Please forgive my poor gaming skills; this video is only for preview purposes (at 2:57, there is a slight lag, which seems to be caused by the computer, not the network).
You can download the original video with its original bitrate from Baidu Cloud Disk or OneDrive, with the extraction code or access password respectively.
Please note that during the game, the mobile data is constantly downloading. For example, playing for 1 second consumes approximately 500 KB of data. During my 12-minute experience, I consumed approximately 820 MB of data. Based on the incoming and outgoing records from Alibaba Cloud, the bandwidth usage was almost maximum during that period.
Personal Experience
Here are my personal observations:
- Public port forwarding: Unless you have your own public IP address (such as through your home broadband), or if the forwarding bandwidth is sufficient, the results may not be ideal, especially for those who are obsessed with image quality.
- Playing games with a controller seems fine. There is some latency, but it is acceptable. However, playing games with a keyboard and mouse results in significant latency, as if the actions are delayed.
- Occasional stutters are still a possibility due to the nature of network connections. Personally, I mainly use it for playing Onmyoji or occasionally fishing in Final Fantasy 14 during breaks at work.