This example deploys a stack with BF2Statistics ASP 3.x.x.
Note that the bf2sclone 2.x.x does not work with BF2Statistics 3.x.x, and so it is excluded from this example. The community has tried to fix it, but so far none seem to have shared their working changes. Wilson212, the original author of BF2Statistics did mention to be working on it, see here, so we might see it soon. If you want to have a working bf2sclone, use BF2Statistics 2.x.x in the meantime.
In this example, we will use the domain name example.com. In production, you should use your own domain name for traefik (our TLS-terminating load balancer) to be able to serve HTTPS for the web endpoints: ASP, and phpmyadmin.
Add a couple of hostnames to the hosts file for the web endpoints:
# Since we are testing this stack locally, we need these DNS records in the hosts file
echo '127.0.0.1 asp.example.com' | sudo tee -a /etc/hosts
echo '127.0.0.1 phpmyadmin.example.com' | sudo tee -a /etc/hostsRun:
docker-compose upIf there is error listen udp4 0.0.0.0:53: bind: address already in use or something similar, the OS might already have a DNS server running on localhost UDP port 53, e.g. systemd-resolved or docker DNS server. To get around that, change coredns in docker-compose.yml to bind to your external interface's IP. Change this
ports:
- 53:53/udpto
ports:
- 192.168.1.100:53:53/udpassuming 192.168.1.100 is your machine's external IP address.
If there is a similar error for TCP port 80 or 443, you might have an existing web server running. Stop the web server first. Run docker-compose up again.
You should see something like:
$ docker-compose up
[+] Running 8/8
✔ Container bf2stats-coredns-1 Created 0.0s
✔ Container bf2stats-init-container-1 Created 0.0s
✔ Container bf2stats-db-1 Created 0.0s
✔ Container bf2stats-phpmyadmin-1 Created 0.0s
✔ Container bf2stats-prmasterserver-1 Created 0.0s
✔ Container bf2stats-traefik-1 Created 0.0s
✔ Container bf2stats-asp-1 Recreated 0.0s
✔ Container bf2stats-bf2-1 Recreated 0.0s
Attaching to bf2stats-asp-1, bf2stats-bf2-1, bf2stats-coredns-1, bf2stats-db-1, bf2stats-init-container-1, bf2stats-phpmyadmin-1, bf2stats-prmasterserver-1, bf2stats-traefik-1The full stack is now running:
- Battlefield 2 1.5 server with
bf2stats3.x.xsupport available on your external IP address on UDP ports16567and29900on your external IP address - Gamespy server
PRMasterServeravailable at your external IP address on TCP ports29900,29901,28910, and UDP ports27900and29910on your external IP address corednsavailable on your external IP address on UDP port53on your external IP addresstraefik(TLS-terminated reverse web proxy) available on port80and443on your external IP addressASPavailable at https://asp.example.com on your external IP address.phpmyadminavailable at https://phpmyadmin.example.com on your external IP address.
If you are behind NAT, you will need to forward all of the above TCP and UDP ports to your external IP address, in order for clients to reach your gameserver and webserver over the internet.
Visit https://asp.example.com/ASP and login using $admin_user and $admin_pass defined in its config file.
Since traefik hasn't got a valid TLS certificate via
ACME, it will serve theTRAEFIK DEFAULT CERT. The browser will show a security issue when visiting https://asp.example.com and https://phpmyadmin.example.com. Simply click "visit site anyway" button to get past the security check.
Click on System > System Installation and install the DB using $db_host,$db_port,$db_name,$db_user,$db_pass you defined in config.php. Click System > System Tests and Run System Tests and all tests should be green, except for the BF2Statistics Processing test and the four .aspx tests, because we still don't have a Fully Qualified Domain Name (FQDN) with a public DNS record.
Then, restart the BF2 server so that it begins recording stats:
docker-compose restart bf2Configure coredns to spoof all gamespy DNS in config/coredns/hosts, replacing the IP addresses with your machine's external IP address which you specified in Step 2.. Assuming your external IP is 192.168.1.100, it should look like:
192.168.1.100 battlefield2.available.gamespy.com
192.168.1.100 battlefield2.master.gamespy.com
192.168.1.100 battlefield2.ms14.gamespy.com
192.168.1.100 master.gamespy.com
192.168.1.100 motd.gamespy.com
192.168.1.100 gpsp.gamespy.com
192.168.1.100 gpcm.gamespy.com
192.168.1.100 gamespy.com
192.168.1.100 bf2web.gamespy.com
192.168.1.100 gamestats.gamespy.com
192.168.1.100 eapusher.dice.seSave the file. coredns immediately reads the changed file and serves the updated DNS records.
Configure your BF2 client machine (and your friends' machines) to use the DNS server (i.e. your local machine) you configured in Step 2.(E.g. 192.168.1.100).
If you are on different networks, you may use any of these methods. Option 3. is recommended.
If you are all on the same LAN network, configuring DNS via DHCP is the easiest. Configure router's DHCP server's DNS setting to your machine's IP address, which will automatically configure all client's machines to use your machine as the DNS server (i.e. coredns). Then ensure coredns forwards all unmatched DNS (all non-gamespy DNS) back to your router so that your LAN DNS remains fully intact. To do so, in config/coredns/Corefile change this line:
forward . 192.168.0.1:53
to your router's IP address (e.g. 192.168.1.1):
forward . 192.168.1.1:53
Restart coredns and it will be ready:
docker-compose restart corednsBF2 1.5 clients should be able to connect to your gameserver. Start BF2, click Create Account, and once you've logged in, click CONNECT TO IP, and in the IP ADDRESS box enter the external IP address of the machine you used in Step 2. (E.g. 192.168.1.100). Join the server.
You may see your server listed under
MULTIPLAYER > JOIN INTERNET, when clickingUPDATE SERVER LIST, but with a wrong IP address, for instance,172.16.x.xinstead of being your external IP address192.168.1.100. This happens because in our exampledocker-compose.yml, thebf2server andprmasterserverare linked using agamespy-network, such thatbf2container registered itself withprmasterservercontainer overgamespy-network, soprmasterserverlisted thebf2server's container's IP address instead of the machine's external IP address. To solve this, run both thebf2server andprmasterserveron host networking, so that they talk to each other over the machine's external interface instead of a docker network.
At the end of the first game, you should see your stats updated at https://bf2sclone.example.com.
- Visit https://asp.example.com/ASP to adminstrate your stats database and gamespy server. Login using
$admin_userand$admin_passdefined in its config file. - Visit https://phpmyadmin.example.com if you want to self-manage your DB (if you know how). Login using user
rootand passwordMARIADB_ROOT_PASSWORD(orMARIADB_USERandMARIADB_PASSWORD) defined on thedbservice in docker-compose.yml - This example includes all the configuration files for each stack component. Customize them to suit your needs.
- Mount the
ASPconfig.phpwith write permissions, or elseASPdashboard will throw an error. UseSystem > Edit Configurationas reference to customize the config file. - For better security, define
MARIADB_USERandMARIADB_PASSWORDfor thedbservice, so that a regularmariadbuser is created on the first run, instead of using therootuser. Note that this hasn't been tested, but it seems to work nicely, although it might break some modules in theASPdashboard if they rely onrootprivileges (any at all?). - Optional: Mount your customized
armyAbbreviationMap.php,backendAwards.php, andranks.phpconfig files if you are using a customized mod. Unlikeconfig.php, they don't need write permissions. - Backup the DB using
mysqldumpinstead of the ASP.System > Backup Stats Databasewill not be allowed since the DB is on remote host. This means there is no need for provisioning abackups-volumevolume. - In a production setup, you want to make sure:
- to use a custom domain name (FQDN)
- to configure
traefikto be issued an ACME certificate for HTTPS to work for the web endpoints - to run
traefikon--network hostor to use the PROXY protocol, so that it preserves client IP addresses - to run the
bf2server andprmasterserveron--network hostso that they: 1) talk to each other over the machine's external interface - to use stronger authentication in front of the
ASPandphpmyadmin, which don't have in-built strong authentication - to use strong passwords for the
ASPadmin user in config file - to use strong password for the
dbusers inMARIADB_ROOT_PASSWORD,MARIADB_USER, andMARIADB_PASSWORD - to use internal networks for the
dbwhich doesn't need egress traffic
These one-liners may be handy for adminstration of the stack.
# Start
docker-compose up
# Only if you are running the BF2 server, PRMasterServer, or traefik on host networking, you may need these iptables rules
# BF2 server
iptables -A INPUT -p udp -m udp -m conntrack --ctstate NEW --dport 16567 -j ACCEPT
iptables -A INPUT -p udp -m udp -m conntrack --ctstate NEW --dport 29900 -j ACCEPT
# PRMasterServer
iptables -A INPUT -p tcp -m tcp -m conntrack --ctstate NEW --dport 29900 -j ACCEPT
iptables -A INPUT -p tcp -m tcp -m conntrack --ctstate NEW --dport 29901 -j ACCEPT
iptables -A INPUT -p tcp -m tcp -m conntrack --ctstate NEW --dport 28910 -j ACCEPT
iptables -A INPUT -p udp -m udp -m conntrack --ctstate NEW --dport 27900 -j ACCEPT
iptables -A INPUT -p udp -m udp -m conntrack --ctstate NEW --dport 29910 -j ACCEPT
# traefik
iptables -A INPUT -p udp -m udp -m conntrack --ctstate NEW --dport 80 -j ACCEPT
iptables -A INPUT -p udp -m udp -m conntrack --ctstate NEW --dport 443 -j ACCEPT
# Attach to the bf2 server console
docker attach asp_bf2_1
# Copy logs from bf2 server to this folder
docker cp asp_bf2_1:/server/bf2/python/bf2/logs .
# asp - Exec into container
docker exec -it $( docker-compose ps -q asp ) sh
# asp - List backups
docker exec -it $( docker-compose ps -q asp ) ls -al /src/ASP/system/backups
# asp - List cache
docker exec -it $( docker-compose ps -q asp ) ls -al /src/ASP/system/cache
# asp - List config
docker exec -it $( docker-compose ps -q asp ) ls -al /src/ASP/system/config
# asp - List logs
docker exec -it $( docker-compose ps -q asp ) ls -al /src/ASP/system/logs
# asp - List snapshots
docker exec -it $( docker-compose ps -q asp ) ls -alR /src/ASP/system/snapshots/
# Dump the DB
docker exec $( docker-compose ps | grep db | awk '{print $1}' ) mysqldump -uroot -pascent bf2stats | gzip > bf2stats.sql.gz
# Restore the DB
zcat bf2stats.sql.gz | docker exec -i $( docker-compose ps | grep db | awk '{print $1}' ) mysql -uroot -pascent bf2stats
# Stop
docker-compose down
# Cleanup. Warning: This destroys the all data!
docker-compose down
docker volume rm asp_prmasterserver-volume
docker volume rm asp_traefik-acme-volume
docker volume rm asp_backups-volume
docker volume rm asp_cache-volume
docker volume rm asp_config-volume
docker volume rm asp_logs-volume
docker volume rm asp_snapshots-volume
docker volume rm asp_db-volumeProblem: The Battlefield 2 client and server binaries are hardcoded with gamespy DNS records, e.g. bf2web.gamespy.com. Because gamespy has shut down, the DNS records no longer exist on public DNS servers (read more about it here). In order to keep the game's multiplayer working, we need:
- A gamespy replacement - solved by
PRMasterServer - DNS resolution for gamespy DNS records - solved by either by:
1.hex patching the game binaries;2.spoofing DNS server responses;3.spoofing DNS records viahostsfile
This example opted for 2. which is DNS spoofing via coredns, because it can be done on a single machine and multiple machine setups.
This is what bf2hub.com and many BF2 mods do.
Pros:
- Simple. Patch every client with the new binaries
Cons:
- Difficult to change to another gamespy server
- Difficult to distribute because it requires installation on each client
- Binaries may be patched with malicious code
Pros:
- Most scalable. You configure the DNS server via
DHCP, so that every client that connects to aDHCPserver (e.g. router) is configured to use the DNS server. No client configuration needed - Easy to change to another gamespy server
Cons:
- Dangerous. The DNS server may be used as an attack vector against clients to steal cookies and direct clients to malicious websites.
Pros:
- Safest. DNS records only apply to the local machine
Cons:
- Difficult to change to another gamespy server
- Tedious to hand edit. See an example of a hosts file here
- Requires administrative privileges to update the machine's
hostsfile
For clients:
- The
BF2statisticsClientLauncher.exewas made to do this - The
BF2GamespyRedirectorimproves onBF2statisticsClientLauncher.exeby allowing clients to save IP addresses of their favourite gamespy servers, and easily switch between them. Read more here
For servers:
- Servers environments should be stable, so
1.or2.is preferred.
For clients:
- The best solution depends on one's setup. If one often needs to switch between gamespy servers,
3.is best. If one doesn't want clients to have to install anything but wants things to "just work", use2.. If one prefers a single gamespy server run by a trustworthy community, use1..