From e6985b6178b292f609fa26ab6798f8ebcf7720fb Mon Sep 17 00:00:00 2001 From: Mikhail Date: Thu, 4 Jul 2024 11:17:27 -0400 Subject: [PATCH] custom launcher UI --- .gitattributes | 2 +- ServerSelector/ServerSwitcher.cs | 1 + ServerSelector/myCA.pem | 34 +++++++++++++++---------------- ServerSelector/myCA.pfx | Bin 2627 -> 2627 bytes generate_ssl_cert.sh | 15 ++++++++++++-- nksrv/Program.cs | 26 ++++++++++++++++++++++- nksrv/site.pfx | Bin 2707 -> 2723 bytes 7 files changed, 57 insertions(+), 21 deletions(-) diff --git a/.gitattributes b/.gitattributes index 327bbd8..af50fed 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,3 @@ # Auto detect text files and perform LF normalization * text=auto -cert.sh text eol=lf +cert.sh eol=lf diff --git a/ServerSelector/ServerSwitcher.cs b/ServerSelector/ServerSwitcher.cs index 4f67ff4..805ddfb 100644 --- a/ServerSelector/ServerSwitcher.cs +++ b/ServerSelector/ServerSwitcher.cs @@ -76,6 +76,7 @@ namespace ServerSelector 127.0.0.1 aws-na-dr.intlgame.com 127.0.0.1 sg-vas.intlgame.com 127.0.0.1 aws-na.intlgame.com +127.0.0.1 na-community.playerinfinite.com 127.0.0.1 common-web.intlgame.com 127.0.0.1 li-sg.intlgame.com 127.0.0.1 data-aws-na.intlgame.com diff --git a/ServerSelector/myCA.pem b/ServerSelector/myCA.pem index d8827a1..103d5a5 100644 --- a/ServerSelector/myCA.pem +++ b/ServerSelector/myCA.pem @@ -1,21 +1,21 @@ -----BEGIN CERTIFICATE----- -MIIDazCCAlOgAwIBAgIUZtfukOBnP/EnpNeODfZtnJychpQwDQYJKoZIhvcNAQEL +MIIDazCCAlOgAwIBAgIUcJP1SCl3PCMhEjSXcn1Ps1Wx+2kwDQYJKoZIhvcNAQEL BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM -GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yNDA3MDMyMDA0MzdaFw0yNjEw -MDYyMDA0MzdaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw +GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yNDA3MDQxNTAwNDRaFw0yNjEw +MDcxNTAwNDRaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB -AQUAA4IBDwAwggEKAoIBAQDGD6bSRP60u1ZYB3HpfrTa4aw+C0cVcez2vIz5Kyy7 -DeMsNy4BA9mW+jhb+fU2UcrfS/890mHGTKWMeJqBL4kHo6jQdvaq9EP7JfQezDPi -6Qzro/En1ruscn8ckZ46jskNjsKgy/YaitAvRt2zUrVfdNIT1l7IPYCARUw9t+FE -UQJXVqmQEWX0gx1zv49uqZdNVeKraZzQim+18h8LmHfAeUN3251dIlQgX727O/pe -TTMNigtgBmKs29++DwIBwi1uIcM2nr/jyBrBGSDEdknKlWNLYD8WVLjnHYheID4f -0xDQBOP7eN+FLaCAI/dkxaUcWfLG0jVxQl+YQxWe0eoxAgMBAAGjUzBRMB0GA1Ud -DgQWBBR3fQt9iIxxmWUJdaDUvkQo1g2mKTAfBgNVHSMEGDAWgBR3fQt9iIxxmWUJ -daDUvkQo1g2mKTAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQB8 -3HwhH1HmKdZpqSsHLmKt4tW7FCpcjrG29WzKMUi5POIGlgqI1MfO5QLe8IUGEVhK -uosOrZmDH5kF8aIGqHYii/o/MHw2p6eHg49hsKRQEU8trN5r3GQbZL0ce0hDTQL0 -dVntSJJ4Pb+Qgm20P4sDPEoFoQ1u2utsYztW6wpw0ksTJtcO2BfMQM/k7egJEv/S -ZRhhl6yA131AI5JSHk3SnUQ/xL1kGL2p6Wixo9accLAcej00+gaDNgxHw1F6OjUt -+XsO807Rqx3TnQwHZyHSijFxSId2JLEO7oCkNeDuuKlU7rb4sh0YIYWWZgS/dG0n -jEOkU1vp7loFpqFdWYVy +AQUAA4IBDwAwggEKAoIBAQCl2jEFtcvfIyvmqz0+RgsaijaU6YsWT4N2Xm+UE5SK +k+C5EuGK/hhaFkIOjWHsxtxvVJQuXJcRZSjGhWLllOnvYtaIvKhvqQ/d1w6AhtoR +KdZw76T4v7p+gcV+3OpJOcYpZMHY9N4i4+gg3ZSXjOMqCbzgmpF5Fyv75nFq+HR/ +ZERt29OH6jLul1oAAcHGbfm5eZY9RS5HS3/uADZjhjnt7MURUes6P/xrWb75wcdD +yLaEwN+DzOZ+VvgbpJmS8hSWkm4e6h/vRsIjKTqnvw7dJIhrkeF7juIM8Z7QY96y +CYWME+hHWWEz0M6yg1GDWt7EuVHzzINpSgbZZhvizDgPAgMBAAGjUzBRMB0GA1Ud +DgQWBBTVvYY5ktXDZNPcsQjIoLMOhb88LTAfBgNVHSMEGDAWgBTVvYY5ktXDZNPc +sQjIoLMOhb88LTAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBx +cXZMZwV8Q4Lfxm3z9cOlG8zp0b5JujeVqv6OV2p+CQ8Py8/R7/DD+IjpZ2QpKJ74 +UUSuqyyrL8zM21yiksgjYYZVxK4USjjL8kIB28Ml0+UmYtfkKmiXJNWs1gGPt8Q3 +aKLMNAj2aHx2vt1+Eu3iex8Pn9RZFsf/tUmxkara1jfVjEeNG/qjt1iM8yXbeyc0 +bx1y8LJKxWo8alux7ncNnDBF3td1ZchhoSg36IX+i6RTM8j/BNCTx3IiiY3hbfaH +hH3FPD4U/Do9+GjidDFVku8OK8MIggYdD02AqR56tG+Sw2RNP35Ky23HcqUyRK5/ +NkmdLtIH+gwww/0oBb4I -----END CERTIFICATE----- diff --git a/ServerSelector/myCA.pfx b/ServerSelector/myCA.pfx index d3dcb143c3064226fa7e43a4c54d4c39a52f55c0..1b178766fa26f253804f1f9d17de21f6497b3661 100644 GIT binary patch delta 2412 zcmV-y36u826vGsdYX}uYw!TVl4o;KQ1R;L`JteY{WYU`{kg}KYLMTdrf&ee{4^ z+wWW%Av~ea>1)033L&3B*cc4br!RNL0u*a#%7Z&Oi{Y~ldQ4Gu5lMO)2e@#Sw}< zZgz1b(B5N0q|=vAvuizUPKx8if^~oHgX~CaaQ|U`WH<;#q6Hxk6@sxHoHPI!O0#PT zXNrrEYI9>9<44V{Mn+)0$m;m!)@M=pwe;7u>v;vFX@}?;a%2rX|H+}4cO2N-@>>l0 z)?EwMsEb+k;&k3ANT=onP&KlY*tzE3%V0Fj`ohh;LTZmYW{Z7)(wh0tLN@%lT!68r13Xu z55D8G-aZJ`X06J4ubNjqXZE~%6_Z+`CJy%B2v1$;wRg(asJXt>=G<6gj zwS`!HRon_nY>TCL-Z_rs&LPSzn9mdVU?nX0LaCVEAAjqF?JD4khfwAjB{?zj? zq;?@T$R@)rPwRneGlz>kH{4vsZD?;n>o@Mhz@A^{kkb{M<;6H2Hr~+v_%M*8IDDv&H+F4TQU*Jic9| z;4LCA3s&7wuB8(^2 zW8^wM^)Lhu4Vx7=#-4v4jsSRG4eebcA%B`vme6g=6oxw}+-hx4gU@4Z)W@1y)IqLg zI77Z^axxCOL*6^lKo|Zl8`J>rfS$L1ORDzXcbGs@`uIIN^}$?Wj@2-N1%w6(Duzgg z_YDCD0ic2fbp(@)1V9LK5exl_lq)ln)C3`aSZZH8Oo1;`t>i6L4FPbZ1cC(631Z3R zG`1)jRiHvHp(xUel%np)Z#w3*ovJ9fkhQ)>;@6*NQ`645HsVam&!xNWu9gR2-Gi;P zq&2vFilBmTGothKXsOU6moBE;;*x?8+dQPSAC0>ViNmw3u~-?syH{TkDRZZfCC(Cm zKD0O*=vHF6TE9g!O@(MNhE6i1rfbSJjSEKI9b3&kHc)FWwvYzpOIm;bxmh=+v$yk* z_2*|vmbu_r)t&fVBRsPnY3A(0BBfB=!gl?%(|(@)IGBtc_Rp}PC8Xh(=;w_27cQ4Q z8@$QkMbsaKAO&5$B1I1ERgOg7>a(DKe0BeezK|hMx;iCeM6u758Pm?cwPH1eN82|I zx~X7w*S3hCMfSBT;Mg@k04ms~Fi7blL6)Z4=mlK%6BLA}4oN_<;srDub!($KCtQ0b zN52`hM_UG;_45MG5h759LX}~7_Fc^;>70?ztb(so`m+#zJ=}Ig%$Xchq8*)oV$t&0 zrRWWa7YB9{2ngE31J26qjVv^AhQTZkFbYOYliMkti8@(_B?rHyaPyZ~o-9m7nb6Y%R&zqWF|woJn;m@8 znfLQ%z@K~NfX2EY~E=p8-QMcTQcit-OlQ!K3_fewn8 zn2RosDlKU`f=Hb3!^;*Ch-1jHE&^bJ;o7CDGQJVT$k^?m}nfHo(CVdtrsvsy{1};}o}CGmGafC#K84^|(td?d;Mag(9o@>b3YWxd|A zc$(7Zb(4ZOPL$0pLMsIYetfzL3W%HC*`IzW{C#nl)WQi#C`(fQwz60~aG0DKv^E;| z&?D}z&p4hUKT>W;5POBEWirZxF7AIs6`T=jK4^B0tedM?f-G2n2k!J;TEBRxd*QZy zSWol0UmL|`oxv)_RQ9}DQ0wKo+)3ODPjiarF1Sui}RFQu=Zi3M3^@2w}$20_dx*Y`SP0Q zXJQU9=OxELQ&5!t<-%%xqrdhshMl!F$qr+_R)LsDthW*fWiea;+A$?CBL)d7hDe6@ z4FL%iF%|?B6jan{RWSS!fQxSd_6r>v;H=u{%#sQfE}FPQ&*9oNG2>!P#`lAQ)2evw e0u7|dtfaBCPBP^^bp!}gX`y=pB2Uo*0tf)svY>DP delta 2412 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 diff --git a/generate_ssl_cert.sh b/generate_ssl_cert.sh index 05102d8..99a64c9 100644 --- a/generate_ssl_cert.sh +++ b/generate_ssl_cert.sh @@ -3,6 +3,8 @@ # Become a Certificate Authority ###################### +set +e + # Generate private key openssl genrsa -des3 -out myCA.key 2048 # Generate root certificate @@ -12,7 +14,7 @@ openssl req -x509 -new -nodes -key myCA.key -sha256 -days 825 -out myCA.pem # Create CA-signed certs ###################### -NAME=mydomain.example # Use your own domain name +NAME=nikkedomains # Use your own domain name # Generate a private key openssl genrsa -out $NAME.key 2048 # Create a certificate-signing request @@ -27,6 +29,7 @@ subjectAltName = @alt_names DNS.1 = *.nikke-kr.com DNS.2 = aws-na-dr.intlgame.com DNS.3 = *.intlgame.com +DNS.4 = *.playerinfinite.com IP.1 = 192.168.3.13 # Optionally, add an IP address (if the connection which you have planned requires it) EOF # Create the signed certificate @@ -37,4 +40,12 @@ openssl x509 -req -in $NAME.csr -CA myCA.pem -CAkey myCA.key -CAcreateserial \ openssl pkcs12 -export -out myCA.pfx -inkey myCA.key -in myCA.pem # Convert site cert to pfx -openssl pkcs12 -export -out site.pfx -inkey mydomain.example.key -in mydomain.example.crt \ No newline at end of file +openssl pkcs12 -export -out site.pfx -inkey $NAME.key -in $NAME.crt + +# copy certs +cp site.pfx nksrv/site.pfx +cp myCA.pem ServerSelector/myCA.pem +cp myCA.pfx ServerSelector/myCA.pfx + +# clean up +rm nikkedomains* myCA* \ No newline at end of file diff --git a/nksrv/Program.cs b/nksrv/Program.cs index 5931e53..1f31044 100644 --- a/nksrv/Program.cs +++ b/nksrv/Program.cs @@ -63,13 +63,37 @@ namespace nksrv .WithModule(new ActionModule("/account/", HttpVerbs.Any, IntlHandler.Handle)) .WithModule(new ActionModule("/data/", HttpVerbs.Any, HandleDataEndpoint)) .WithModule(new ActionModule("/media/", HttpVerbs.Any, HandleAsset)) - .WithModule(new ActionModule("/$batch", HttpVerbs.Any, HandleBatchRequests)); + .WithModule(new ActionModule("/$batch", HttpVerbs.Any, HandleBatchRequests)) + .WithModule(new ActionModule("/nikke_launcher", HttpVerbs.Any, HandleLauncherUI)); // Listen for state changes. //server.StateChanged += (s, e) => $"WebServer New State - {e.NewState}".Info(); return server; } + + private static async Task HandleLauncherUI(IHttpContext ctx) + { + await ctx.SendStringAsync(@" + + +Private Nikke Server Launcher + + + +

What's new in Nikke Private Server

+

This is the inital release, only story mode works except that you can't collect items and a few other things don't work.

+

In order to level up characters, you manually have to edit db.json

+ + +", "text/html", Encoding.UTF8); + } + private static async Task HandleBatchRequests(IHttpContext ctx) { var theBytes = await PacketDecryption.DecryptOrReturnContentAsync(ctx); diff --git a/nksrv/site.pfx b/nksrv/site.pfx index df72a49661262be6558966d6df086180efd790c6..8cf0cac998a736eef325ac908b5e4c74179118e1 100644 GIT binary patch delta 2556 zcmV&QwU3N~hN9la>8 z$fOca{&@V;YWJnte<~LJqO|}Nls@Z*f9c`@x4kn+{Eq(Z>m2&vlzj(Gtu=2Ba_fQn zGY8$AdgNvJF>@3N`{!+9RGnG~ezjSC$h?{vCYXdYnT#w)-{B*|e}ak+AO$@Bb`MH! z_?A&5-B-s0O$0pneDqHVOU70Qq(EK2SNC{Y7VAI4iLYOkfAWS!kRvFBX#;4~3=Mo5 z`J};%#m;2KR`Jaj@M@JDd{JUrV;{6Nb^EH$DA}tZX&#Ki?%MZ`%zC=X0jXRbZb#{q zGzjm}Dgy3vsl;=3p|CZ1WHVJae0Zc16?U zZifzkO#9DUBF(HHDuq`2P6v9-JVNBd(Fos;I;%1jj2R`!UYU--+i%JQKSg19RWuu* zc&pcee{6T);Ll?Qp?d-(`B_ zb+|Z_y`ix5E?OWCGNn4uI;u)!wAla27|I^Xnj1EQVYNjCMUYBRhW@+CFD?s>4@^`t ze^FJC0TdxKG$3j3-V3I%i$)}rb_@%~|6{tXCud>>z&>f`Cid?quwoe6Y!TiVmYB`` zQM%VDhVH(T2EM1NmqSD}YWW!yJ00m|3Ka@&0nC$kDoB9) z2?Sr9&~D9M;1K0eP5%)#`Q_OBj0GkET^PE86-SyL9fjT`q1`$P1;x^v@OSp~PGsguYA zR0wZW1ZhMODQc4>1tEXhf!rA-T5{3>WJl|7Xve(-f&|dE4?RvAuND3tQGU%b9oorP zYnX)F5AY1?=RjPn94$>9NQ99VNAbbcs}IL&EM(jZe(gJ;6Yl$d`D-mL;3m(3p5ZMP{URX;iryz%16$#T8J zNnL>FSNd;q3>n$$ATZ06o&@&4+OS9-*<*6C{s;|c#HS_P(%)>VRxhW{4Bw0Y87{jg z{g}2q86r!S;~RX>LuxXva3i}YI6%iIxoM&_qO{Q-D`qk6T7oE*LR096Q{BfX{-Bg zDt>0zb_hjQNB$lu@O0CoQu^w#6A6oL2L<^hIS?Bw(pw8TPZKP9iNzD z-g!6~du@(!Nw?<<~hN?PkZ(>iNLy zJhXp0;Ybd!CvmY~+k*xJzumnXp>yF~zbY7C*$px}6w3C|i0O z&%Rl>TQTt{< zhZ)eQ&;nVga=!iUO>1r5XtorZ&k1s@*&%ykN%%xPWI%R2_7?=EeWMw|U-|TY=kpI`|q@h4_;h7@?!RqGqv=YkqfBAoO z>^a4>SnyYY2GafLuF(oh~1_>&LNQU04lTZp3E|-2lWhWs{S!i^(A#vIG(aoOzBoWubPNw9p@}u9% SD+CB=!6{D?ohaP`0tf&ff#etf delta 2540 zcmVOUE<o?`JzT;RpfAJluuZzawZj8ga@+Xa;DK(<-hm)*9p=(GZpDUjZkB1JM>Gf#f9A zhso&fX`GB4{mk~AE*$@_L3?Ymo}&n*&U(B!1c|TdLR?fO9wnh6nB{!im*g6z-%pNh zPK}eyeWtFVvHYROirGgYK;8Z!C)O24+pFwg1}L9}&3HODM$Xd;j?xeoZe|RHeQa<; zX;qqK`48`>e}-?LHsZ+J=i|EInS#kmi=V=Ahz;t#Ue_(3vlGRHu7)&Vlu;nc0+XLS{ z?8yEgH{ra-+Z)ci^9Ry+)O&;AIYRaTuWUJQv?XS_slZ@daZ6@Yio>bQR*fAFfR*4 z4u0&se-2?*Y!ZY|fMYKe9_S_F`@PO5;I`c8*c&32ISZ1r{cWd03R`#Q$N?+%Zy=6c zBpmMjeIM#;m+Q(8ZP#xrt5!{)!|w|% zS{+AZQ_Z}C{1C=D59IKRX@ERLAzd}qV~Hn&fB5Jgeo3u;sZ1PL2H<`czOrpmG#vJf zd_{9?m|=wlu-mCSn|EOSs#;8Qr0OjVV1zAmnjEPw){O{D2F7r_3I8VqnDC9fP<9tE=E;8NJf^lcJgmBp-29$!f@dluJ4gx|`2vv&wUeyq-0#hh z_Ks(TX#RlO!-j%#f?`3YrH|s9v{(ca zKx_}ys7O?6S_h~;YkStYmq&V|f6er7(MIeLBXJKuGT8s-cjS5P7E)al@4Z5bO-)(uGXSj_7(-6i+2SUYMl6Q zy~t$(GsoeKRmoc&57S_0jDdWWcv9@VwA}`$rMs+J@V_d;-Mt@aU-+Uk5y?pbFh5&| zB&?+XQ&KF|bEo~K+r~GZ_-l}!D9ejRx8)`Tq<1;Tp~oB%M=5(u(aNB&YUF6Gh?0BhBwI@Nt~6ZJf8d9lgn7HkMBY|GWs86B{SimzlX$V<&-%AxN0i5U=n zpHAeGpP@61mp$MjVf>dSi#FT+15&*ro+eMa-uK=uAOkWoC+Z%rLm~A@x$cSqOCOi> z>pO2TGjKVO#Ok2P+X_#0mP>!7{=xWAM~%5x4GOQqE>au8L(k-J;4+^e^Is(>z8w_( z0eEXX8C3$ES@~}zF*o+rjmFhsy|t1kuhRVrNr@M`Q(S%h_WIv-i5C)1BDr@EC*`3R zY-^)AM@NfpLgq%Rr#5@)eJM=`E{UXv)>)#uV6=s>V$!%XjK5+`)iHmcGd{)pY0BsO zSh?YF9NbT(VJ=LjO!4Ce9i|02pEna982MImbE_4bmd?R2&OkY~+XKLu!>NB}`O?oJ z#)hS9qUsY##JNUN{^imEs)HfT5VhTp$f@o)bB|U%Rzu2a)A2m*IPnpW;GVutHbzElN{L0p{~gu3s%n>1-`Aj{Y-hW&Jm*X z)P#HwTIPlAX!uSVQ$pm}V54JckM6^5`jQ-qPpoL0xO4O+nH69HZoc4}(pG?wLYo!R zycrgIaL<#sz^ghUf)Um8(f=Z&WK$bmW&Ln>Tg)w~d7O*oW#@nE9OF^4@CVDg)^8JZ zH~R*cd5KJI=bn|A**U!tDZgQ}fHAh`E|-e3(g?G(;tZC?l0 zqjMg72J3B`I1zsg9=0@vEw;zqKPh5=pfFXP=W;u#5h9FGxlh78bG0$6fsrgVzSyio zL0OkZnMyWBq~s-4rvmc+hbFK+=i~(Tljf!!nAqGvEsZ3=Do`lPmN0Az#g4%dF~%m_ zf?i1U+~>Ubib@U4YL;~)9|@owZYNei_*D8KM5XVXK-(vXMZf1h?6AG#BBkV=V~^}}bfg{H_T4v(o6DY3 z`NEB-hfhwvlAlv4F(oh~1_>&LNQU|h}*ESmr2T)s`!A17cl>Vq1D*B0F