Das ist so hammer reudig und doch weiß ich, dass ihr das so todernst meint..
Beiträge von Lead0b110010100
-
-
Gibt es eine möglichkeit dies zu deaktivieren ?
Bitte melden Sie sich an, um diesen Link zu sehen.
-
Der Service ist bis zum 29.05.21 pausiert, Dauer & Stammkunden sind davon nicht betroffen.Wenn ich nicht antworte, bitte geduldig sein und in einer Woche nochmal schreiben.Brauch nur mal Urlaub von dem Kram und muss ein paar Arzttermine nachholen, nichts Wildes!P.S: Ihr seid echt wie brennende Schafe die in alle Richtungen laufen, ihr habt nicht mal eine Woche ausgehalten Bin wieder da, hab euch lieb.
-
Kleine Anmerkung:
Wenn ich mich auslogge und wieder einlogge, dann bin ich nicht mehr locked.
Denn du persistierst diese Variable 'm_isLocked' nicht weiter, die wird bei CHARACTER::Initialize wieder auf false standartmäßig gesetzt.
Also Client killen und neu starten und dann hat sich das.
-
Es ist zwar echt nett das du gefundene Lücken releasen willst, aber es schadet gleichzeitig deinem Geschäft.
Ich würde mir diesen Punkt also gut überlegen und allgemein ist es besser, 'Services' anzubieten, die monatliche Zahlungen beinhalten anstatt deine Zeit gegen Geld zu tauschen.
-
Würde entweder Lead0b110010100 oder MrSIB empfehlen aber ob die das machen ist eine andere Frage
Hey,
vorerst danke für die Empfehlung. Ich habe und werde nicht den ganzen Source durchgehen. Wenn die Basis clean ist könnte man anhand Git oder Defines die eigene Arbeit anschauen. Bei entsprechender Bezahlung könnte man es sich überlegen.
Sobald welche gefunden wurde, benötigte ich zusätzlich einen Fix.
Das ganze wird anschließend mit einem Betrag X belohnt.Wenn du nur für den Fix zahlst und nicht die noch aufwendigere Suche, dann wird es wohl keiner tun.
Geh ich mit.
-
I love it
-
OH wow, dude. That's awesome!!!
I wish I could like that thread 5 times more, that will open a whole new set of features that could be implemented. I never even thought of that idea of bringing events to the client too (The way with python and the OnUpdate function get's really messy over time).
I am installing this in my code base right now, thanks!
-
Oder einfach einen std string nehmen und nicht unnötig viel speicher allozieren
Yesn't.
Bitte melden Sie sich an, um diesen Link zu sehen.
-
Moin.
Da ich immernoch am ausprobieren sämtlicher Tools und Hilfestellungen bin und heute random die Option zum "AdressSanitizer" in Visual Studio gefunden habe, dachte ich schadet es nicht wenn ich einen potenziellen und offensichtlichen Fehler mit euch teile. Gleichzeitig empfehle ich jedem angehenden Entwickler folgendes Video hier:
Bitte melden Sie sich an, um dieses Medienelement zu sehen.
-------------------------------------------------------------------------------------------------------------------------
Was zum Fick?
Ums kurz zu erklären, was tun wir in den folgenden drei Zeilen Code?1) Wir erstellen ein char array im Stack mit der Länge / Größe 36. Also können genau 35 Zeichen + im Optimalfall (üblicherweise) der Null-Terminator '\0' reingeschrieben werden ins Array.
2) Wir schreiben einen formatierten String in den Buffer, grob gesagt. Eigentlich streamen wir den formatierten String in ihn, aber gut.
3) Wir geben den String als Teilkomponente in der sys_log aus, dafür benutzen wir den Variablennamen für das Char-Array also 'name'. Was eig. nur ein Pointer auf das erste Zeichen im Array ist, wenn mans so will. Beim Ausgeben liest dann das Programm von diesem Pointer aus im Speicher die Stellen und gibt sie aus bis ein '\0' - Terminator kommt.
Setzen wir doch mal einfach Werte in den formattierten String ein und schauen uns z.B an was passiert wenn ich als Serverbetreiber '100x Zen-Bohne' im Shop verkaufen möchte und in die shop_item in der Datenbank so eintrage:
Sieht harmlos aus oder? Wie viele Zeichen sind das? (Es sind genau 36)
Es fehlt also der Platz für den Nullterminator im char array, snprintf wird das Array nicht vergrößern. Stattdessen findet man bei der Recherche folgendes über den Rückgabewert der 'printf' - Funktionen:
Return Value
Let len be the length of the formatted data string (not including the terminating null). len and count are in bytes for _snprintf, wide characters for _snwprintf.
If len < count, then len characters are stored in buffer, a null-terminator is appended, and len is returned.
If len = count, then len characters are stored in buffer, no null-terminator is appended, and len is returned.
If len > count, then count characters are stored in buffer, no null-terminator is appended, and a negative value is returned.
Wir haben ein Char Array der Größe 36 erstellt und genau 36 Zeichen reingeschrieben. Demnach ist dieser 'string' wenn mans so sehen möchte nicht null terminiert. Der char - Array resultiert also eig. in sowas hier was wir nicht wollten:
Es werden mehr Zeichen repräsentiert als angegeben (36), weil im Speicher nun zufällig erst nach 4 random Zeichen der Nullterminator kommt. Das könnten auch 500 Zeichen sein, oder gar keiner. Also wenn ihr noch keinen Crash beim Hochfahren des Servers hattest, hattet ihr entweder einen wirklich schlauen Compiler der das erkannt und die Gefahr gebannt hat oder einfach Glück.
Wie fixxe ich das nun?
Ganz einfach, macht den Buffer entsprechend größer. Theoretisch reicht es, ihn auf 40-50 zu setzen. Ich nehm jetzt einfach 512 um ultra sicher zu sein (Nutze damit mehr Speicher im Stack, ist aber unproblematisch, weils schnell wieder gecleared wird und nicht dauerhaft da bleibt):
shop.cpp
Suchen
Ersetzen mit
Was lernen wir daraus?
Wir sollten alle Tools nutzen die es gibt um unser Programm bestmöglichst zu härten und Bugs vorzubeugen.
Bugs erst zu fixxen, wenn sie auftauchen ist keine Good Practice. Vieles kann vorher schon verhindert werden.
-
Good job, hab zwar noch niemanden gesehen der dieses Paket aktiv nutzt um Buffer Overflows zu erzeugen - Aber bei genug Paketen ist das aufjedenfall möglich.
War mir bisher so nicht aufgefallen und wäre es auch nicht denke ich (bis mich jemand aktiv mit dieser Methode angreift).
-
Moin Community,
dieses Thema sollte nicht zu ernst genommen werden und diente eher als eine Art Experiment um die Möglichkeiten
einer MMORPG Serverarchitektur zu testen. Die gesammelten Erfahrungen würde ich bis zu einem gewissen Grad teilen
und eventuell kann der eine oder andere auch weitere Ideen reinbringen. Vorab möchte ich sagen jeder der diesen kleine Bericht
liest und mich anschreibt und fragt ob er die Serverfiles für dieses Projekt haben kann, es gleich lassen kann. Mir gehören die Fiels nicht
und habe selbst nur ca. 5% des Codes beigetragen. Ich habe hauptsächlich die Infrastruktur aufgesetzt und verwaltet, sowie
die Architektur designed.
Worum geht es denn nun eigentlich ?
Wie die meisten wissen handelt es sich beim Metin2 Server um eine monolithische Anwendung
"Monolithic applications are designed to handle multiple related tasks. They’re typically complex applications that encompass several tightly coupled functions.As you can imagine, given their broad scope, monolithic tools tend to have huge code bases. Making a small change in a single function can require compiling and testing the entire platform, which goes against the agile approach today’s developers favor."
Heutzutage setzen wir im modernen Umfeld auf Service basierte Architekturen, dass heißt wir brechen große Applikationen in mehre, teilweise auch hunderte kleine Applikationen auf und lassen die miteinander kommunizieren. Dies hat viele Vorteile wie:
- Einfach zu maintainender code, da die Services unabhängig voneinander funktionieren und ledgelich eine abstracke Schnitstelle bieten
- Seperations of concerns: Ein service hat immer nur 1 Aufgabe/Domain die er behandelt.
- Übersichtlicherer Code
- No single point of failure
- Schnellere compile times
- Gezielte verticale/horizontale Skalierung
- etc.
Wir haben im Rahmen dieses Experiments die Serverarchitektur in 3 Services aufgeteilt (ja man kann diese noch weiter aufteilen, aber wird extrem complex)
- Auth
- Chat ( Beinhaltet nur den Worldchat sowie private Chat + offline messages)
- World
Was mussten wir vorher erledigen?
- Update den komplleten Serverside & Clientside Code auf C++17/C++20
- Update sämtlicher Libs
- Update des MySQL Connectors
- Anpassungen der SQL Query systems
- Rewrite des kompletten Chat Systems
- Rewrite des kompletten Auth Systems ( Implementierung einer Methode, sodass die anderen Systeme/Instancen vom Auth wussten)
- Rewrite des Networkings
Wie hosten wir so eine Architektur?Gute Frage wir hosten es natürlich in der Cloud. In welcher Cloud ? In unserem Fall haben wir das Experiment in der GCP (Google Cloud Platform) gehostet.
Aber gleichermaßen hätten wir Aamazon Web Services, Microsoft Azure, oder IBM Cloud oder Digitalocean verwenden können. Ja uns ist es bewusst das diese
aktiv gegen DCMA vorgehen aber mit einer TCP proxy vor dem ganzen System wird der Traffic nur den proxy geroutet und keiner weiß wo ihr eiegentlich hostet.
Welche Services verwenden wir?
- GKE Autopilot ( Manged Kubernetes Kluster im Autopilot modus)
- Compute Engines (Fancy name für VPS)
- Cloud SQL (Fancy version of MySQL in der Cloud mit sharding und edge locations)
- Cloud Bigtable ( NoSQL Database für Playerlogs (werde ich nicht thematisieren))
- Cloud Amor ( Firewall von Google (werde ich auch nicht thematisieren))
- Cloud Loadbalancing
Bitte melden Sie sich an, um dieses Bild zu sehen.
Was ist Kubernetes?
Kubernetes ist ein Container Orchestration System. Es erlaubt uns Services in Docker Containern zu definieren und diese automatisch zu skalieren.
Jedder Container ist ein sogenannter POD. Diesem können mehr vCPUs oder Ram je nach Auslastung zugewiesen werden. Da aber nicht jeder Service
mit mehr Ressourcen besser skaliert, können auch sogenannte Replicas eingesetzt werden. Das sind exakte kopien des Services und die user werden mittels
des Cloud Load Balancers auf die Instanzen verteilt. In GKE können wir Scaling-Rules setzen z.B. je nach Network/vCPU/RAM Verbrauch. Beispielweise sagen wir
user Auth POD hatte eine Rule für Replica-Saklierung bei 80% Auslastung von vCPU und RAM. Sollte dies erreicht werden instanziert das System automatisch eine weiteren Auth Server.
In diesesm Beispiel erlauben wir es nur den Auth Service mehre PODs zu instanzieren. Chat und Game Server bekommen je nach Auslastung mehr Hardware Ressourcen zugewiesen.
Außerdem prüft Kubernetes ob die PODs noch alive sind, sollte einer nicht mehr funktionieren, wird dieser zerstört und ein neuer aufgesetzt.
Was bringt uns das jetzt?
Ganz einfach kosten sparen und je nach auslatung nachskalieren und unnötigerweise selber einen neuen Server aufzusetzen.Wenn Beispielsweise nur 100 Spieler online sind skalieren die PODs runter z.B. downscaled der Server von 4vCPU und 8 GB Ram runter auf 2vCPU und 4 GB ram. Je nach Auslastung.
Wir nutzen nur die Ressourcen die wir wirklich brauchen. Dies spaar uns Kosten, da das Billing teilweise pro Sekunde/Stunde funktioniert.
Was haben wir beobachtet im Rahmen des Experiments:
- Reduction in Packetanzahl/Packetcomplexity um ca. 10-20% auf dem Gameserver
- Du bekommst den Server nicht down, beim besten willen nicht. Es sei du hast Fehler im Code.
- Bugs mehr als Deadline 2 - wir haben nicht alles gefixt, da es nur ein Experiment war
- Metin2 in die Cloud zu ziehen ist lustig aber absolut Sinnlos, solange man keine License hat
- Teuer für normale Hosting Verhältnisse wie OVH, HETZNER etc.
- Viel Zeit & Erfahrene Entwickler braucht es
- Einer musste Cloud Kentnisse haben und basic DevOps Knowledge besitzen
- Lasst es einfach sein wir haben eigentlich nur Zeit verschwendet.
Nun die Kosten:
- Cloud SQL : Pro vCPU 36,1$ , Pro GB RAM 6,13$, PRO GB SSD Speicher 0,17$ (Alles pro Monat)
- GKE Autopilot: Pro vCPU 32,4850$ , Pro GB Ram 3,5934245$, Pro GB SDD Speicher 0,04$ pro Monat, GKE 0,10$/STD Mangement Gebühr
- etc.
Am ende hätte man bei Livebetrieb eine Rechnung pro Monat im Bereich von 500-1500€ je nach Spieler Anzahl. Achtung vor Kostdeasters!
Es gibt keine Billing Limit, da ihr Kreditkarte oder Konto hinterlegen müsst. Ihr könnt den maximalen Verbrauch über Billing Rules setzen.
Fazit:
Wie ich schon mehrfach angeteasert habe war der Zeitaufwand viel zu hoch und auch die Hostingkosten rentieren sich nur für die größten Server.
Ihr solltet also nie mit dem Gedanken spielen Metin2 Cloud ready zu gestallten. Aber für diejenigen die eventuell davon träumen irgendwann
ihr eigenes Spiel zu entwickeln kann ich die Cloud nur empfhelen. Am Ende dieses Projektes ist ein halbfertiges Produkt entsanden welches
mehr Bugs und Probleme besitzt, als es uns Lieb ist.
Ich danke euch dass ich eure Zeit verschwenden konnte.
Ich finde es sehr gut, dass du nicht nur von den Vorteilen und Möglichkeiten erzählst sondern direkt auch alle Illusionen zerstörst zwecks Kosteneinsparung und Umsetzbarkeit.
Wie du schon sagtest, brauch es dafür wirklich fähige Developer (Nein, ein einziger wird da nicht reichen) und einen, der sich mit Clouddiensten auskennt.
Klar, ich kann bei Google Cloud Server kaufen, aufsetzen und skalieren - Aber ich verstehe nicht ansatzweise genug um das architektonisch am Ende auch schlau und kosteneffizient umzusetzen.
Good job - Ich mag solche Experimente. Gerne mehr davon, ist immer schön zu sehen was theoretisch so geht (Auch wenn praktisch bei Metin2 wirklich unnötig. Cloud und Gameinstanzen zu separieren find ich noch sinnvoll aber den Chat? Naja..).
-
Moin,
ich möchte zur Handshake Phase (Auth) ein neues Packet hinzufügen, habe Clientside und Serverside soweit alles programmiert, bekomme nun aber auf dem Loginserver folgende Fehlermeldung:
Muss ich, um das Packet verwenden zu können, noch den Sequence Table anpassen? Oder gibt es irgendwo eine Zuweisung, welche Packets zum Handshake zugelassen sind?
packet_info.cpp (Server-Source) und PythonNetworkStream.cpp (Client-Source)
Da ist für jedes Paket nochmal spezifiziert ob es ein statisches oder dynamisches Paket ist.
-
Danke, das wusste ich tatsächlich nicht.
Hab fairerweise auch nie nach den Properties gesucht, ich weiß auch nicht was eine ".rc" Datei ist oder macht und hab nicht vor zu googeln.
Aber danke.
-
Darf ich es automatisieren ?
Ich liebe diese Frage.
-
Ich sehe das nicht so eindeutig, um mir eine qualifizierte Meinung zu bilden.
Einerseits erledigst du, .colossus. hiermit deinen einzigen Konkurrenten der ein ähnliches System anbietet und erhöhst damit deine Reichweite und damit auch deinen Profit.
Andererseits spielt dein Konkurrent auch nicht fair, zumindestens wenn man dir glauben will und ist selbst nicht ganz töfte unterwegs.
Ist es also okay, so ein "HOW TO" ohne wirklichen FIX zu veröffentlichen? Das muss jeder für sich selbst entscheiden, ich finde: Nein.
Du schadest mit diesem Thread nicht nur diesem 'gefährlichen' Menschen sondern auch jedem Server der seinen Service in gutglauben angenommen hat.
Technisch muss ich hier aber trotzdem noch erwähnen, dass mir und jedem mit dem ich gesprochen habe zu diesem 'Fix' bereits beim ersten Durchsehen der Bottleneck (Webserver) und der laue Schutz (whitelist von ips über GET) aufgefallen ist und das auch ein Grund für mich war, von diesem Schutz abzuraten. Also wenn .colossus. dieses HOW-TO gemacht hätte, hätte es wahrscheinlich ein Anderer gemacht. Oder noch schlimmer: Ein Angreifer hätte darüber erfahren und hätte dann explizit die Webserver der Server angegriffen, die den Schutz gekauft haben.
Schwierige Sache, für mich keine "gut oder böse" - Frage.
-
Bin ich grade, willst du ein Video?
Dir fehlt einfach nur der Flag in der skill_proto:
DISABLE_BY_POINT_UP
So muss das dann aussehen:
Bitte melden Sie sich an, um dieses Bild zu sehen.
Ach so meinst du das. Klar wäre auch eine Möglichkeit, da aber unbenutzt kannst es auch gleich raushauen.
So ganz unbenutzt ist es nicht. die ANTI Skills z.B müssen initial mit Skillbüchern und danach per Point gelevelt werden.
Diese passiven Skills könnte man da aus meiner Sicht echt entfernen in der cmd_general, würden durch die Abfrage sowieso verhindert werden.
-
Was gibt es da auszunutzen? Es passiert nichts.
Hab das aus der Kraizy Source da oben, kein Exploit zu sehen. Vllt. erklärst du den nochmal genauer?
Habs btw. ausprobiert, bei mir passiert da nichts bei /skillup 141/142 usw.
Wenn du den in der skill_proto hast kannst mal mit dem debugger durchsteppen.
SQL- INSERT INTO `player`.`skill_proto`(`dwVnum`, `szName`, `bType`, `bLevelStep`, `bMaxLevel`, `bLevelLimit`, `szPointOn`, `szPointPoly`, `szSPCostPoly`, `szDurationPoly`, `szDurationSPCostPoly`, `szCooldownPoly`, `szMasterBonusPoly`, `szAttackGradePoly`, `setFlag`, `setAffectFlag`, `szPointOn2`, `szPointPoly2`, `szDurationPoly2`, `setAffectFlag2`, `szPointOn3`, `szPointPoly3`, `szDurationPoly3`, `szGrandMasterAddSPCostPoly`, `prerequisiteSkillVnum`, `prerequisiteSkillLevel`, `eSkillType`, `iMaxHit`, `szSplashAroundDamageAdjustPoly`, `dwTargetRange`, `dwSplashRange`) VALUES (141, 0xC1F5C7F7, 0, 1, 40, 0, 'NONE', '1333.3*k', '', '', '', '', '', '', NULL, '', 'NONE', '', '', '', '', '', '', '', 0, 0, 'NORMAL', 0, '1', 0, 0);
Bin ich grade, willst du ein Video?
Dir fehlt einfach nur der Flag in der skill_proto:
DISABLE_BY_POINT_UP
So muss das dann aussehen:
Bitte melden Sie sich an, um dieses Bild zu sehen.
-
Ist mir schon klar, jedoch wird das von ein paar Spielern noch ausgenutzt, was vor allem im PVP ärgerlich ist
Was gibt es da auszunutzen? Es passiert nichts.
Hab das aus der Kraizy Source da oben, kein Exploit zu sehen. Vllt. erklärst du den nochmal genauer?
Habs btw. ausprobiert, bei mir passiert da nichts bei /skillup 141/142 usw.
-
Es war nie ein Exploit. Denn beide Skills haben den Flag:
und folgende Abfrage in der SkillLevelUp Funktion verhindert den 'Exploit'. Diese existiert standartmäßig:
Für die ANTI - Skills verhindert folgende Abfrage das initiale hochleveln (lvl 0 zu lvl 1):