Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Access limit by user/pass #4

Closed
roointan opened this issue Mar 16, 2023 · 13 comments
Closed

Access limit by user/pass #4

roointan opened this issue Mar 16, 2023 · 13 comments

Comments

@roointan
Copy link

Is access limit by user/pass available out of the box?
If not, do you think it'll be easy to add?
Can you guide me in implementing it myself, if you don't have time yourself?

@Lyoko-Jeremie
Copy link
Collaborator

Lyoko-Jeremie commented Aug 7, 2023

sorry for my delay.


oh ~ it's a rare use-case. Only very few users need auth .
do you want which user/pass ? in the
(1) Socks5BalancerAsio -> backend server side (upstream side)
OR the
(2) client -> Socks5BalancerAsio side (downstream side) ?


i think all you want to do in the handshake can place in FirstPackAnalyzer

the FirstPackAnalyzer class impl the http-proxy/socks5-proxy on same port mode (aka mixed-port mode) .

it init when a new client connect come , at the handshake from TcpRelaySession :

firstPackAnalyzer = std::make_shared<FirstPackAnalyzer>(

it check the first 3 byte from client , and check it is a normal socks5 connect or a http connect :

boost::asio::async_read(
downstream_socket_,
downstream_buf_,
boost::asio::transfer_at_least(3),
[this, self = shared_from_this(), ptr](
const boost::system::error_code &error,
const size_t &bytes_transferred) {
if (!error && bytes_transferred >= 3 && downstream_buf_.size() >= 3) {
// check first 3 byte
auto d = reinterpret_cast<const unsigned char *>(downstream_buf_.data().data());
if (d[0] == 0x05 &&
d[1] == 0x01 &&
d[2] == 0x00) {
// is socks5
std::cout << "is socks5" << std::endl;
connectType = ConnectType::socks5;
// relay normal
do_prepare_whenComplete();
} else if ((d[0] == 'C' || d[0] == 'c') &&
(d[1] == 'O' || d[1] == 'o') &&
(d[2] == 'N' || d[2] == 'n')) {
// is http Connect
std::cout << "is http Connect" << std::endl;
// analysis target server and create socks5 handshake
connectType = ConnectType::httpConnect;
do_analysis_client_first_http_header();
} else {
// is other protocol
std::cout << "is other protocol" << std::endl;
// analysis target server and create socks5 handshake
switch (d[0]) {
case 'P':
case 'p':
// POST, PUT, PATCH
std::cout << "is POST, PUT, PATCH" << std::endl;
connectType = ConnectType::httpOther;
break;
case 'G':
case 'g':
std::cout << "is GET" << std::endl;
// GET
connectType = ConnectType::httpOther;
break;
case 'H':
case 'h':
std::cout << "is HEAD" << std::endl;
// HEAD
connectType = ConnectType::httpOther;
break;
case 'D':
case 'd':
std::cout << "is DELETE" << std::endl;
// DELETE
connectType = ConnectType::httpOther;
break;
case 'O':
case 'o':
std::cout << "is OPTIONS" << std::endl;
// OPTIONS
connectType = ConnectType::httpOther;
break;
case 'T':
case 't':
std::cout << "is TRACE" << std::endl;
// TRACE
connectType = ConnectType::httpOther;
break;
default:
std::cout << "is default..." << std::endl;
connectType = ConnectType::unknown;
break;
}
// debug
do_analysis_client_first_http_header();
}

(A) if it's a socks5 header 0x050100 , call the do_prepare_whenComplete() back to TcpRelaySession continue the relay as a raw TCP .
this is the socks5-proxy/socks5-proxy mode, and can be simple as raw TCP relay mode. in this case, the client socks5 handshake direct send to backend server (the backend server direct do the handshake with client, we dont touch it).

(B) if it's seems like a http header , call the FirstPackAnalyzer::do_analysis_client_first_http_header() to begin the http-proxy to socks5-proxy process, it

  1. handshake http-proxy with client, do_analysis_client_first_http_header()
  2. read client connect target (IP/domain) from client,
  3. handshake socks5-proxy with backend server , do_socks5_handshake_write()
  4. send connect target (IP/domain) to backend server,
  5. complete the socks5 handshake with backend server,
  6. now, two side handshake complete !
  7. call the do_prepare_whenComplete() back to TcpRelaySession continue relay remaining data as a raw TCP .

if you want impl Auth in CASE (2) client -> Socks5BalancerAsio side , you need split (A) and impl a new socks5 'server side' hanshake impl in (A) client side (downstream side) for the socks5-proxy/socks5-proxy relay mode AND insert a 'server side' http (downstream side) auth in (B) for http-proxy/socks5-proxy relay mode.

if you want impl Auth in CASE (1) Socks5BalancerAsio -> backend server , you need split (A) and impl a new socks5 'client side' hanshake impl in (A) backend server side (upstream side) for the socks5-proxy/socks5-proxy relay mode AND add a 'client side' socks5 auth (upstream side) in (B) for http-proxy/socks5-proxy relay mode.

@Lyoko-Jeremie
Copy link
Collaborator

OR, because impl the CASE (1)(2) have duplicate place. so we can impl they two.

split (A) to do the socks5 handshake with upstream and downstream, so we can make a auth with server and client in socks5-socks5 mode.
insert socks5 auth to upstream and http auth to downstream in (B), so we can make a auth with server and client in http-socks5 mode.

@roointan
Copy link
Author

roointan commented Aug 7, 2023

Oh this seems more complicated than I expected. Let me revisit this later.

For more information on my use-case, I need client to be able to connect to Socks5BalancerAsio, only with a valid user/pass.
This is because I run Socks5BalancerAsio on a server inside the country, and not on my own machine.
Right now I'm using iptables filters, and use helper scripts to allow certain IPs to connect.
When I'm on a new ip (which happens a lot when I'm on mobile data), I need to open a web page and wait about a minute, to be granted access.
If Socks5BalancerAsio supported user/pass for socks5, iptables filtering wouldn't be needed and I could access the server much more easily.

And thanks for sharing Socks5BalancerAsio, I'm using it daily and extensively, has been a lot of help to me.

@Lyoko-Jeremie
Copy link
Collaborator

Ok~ thanks for your use Socks5BalancerAsio .

i will impl it later . please wait some times.

@Lyoko-Jeremie
Copy link
Collaborator

Lyoko-Jeremie commented Aug 10, 2023

Hi~ the auth impl now.

about more information and how to enable it, please see the README Auth Support section.

now the Auth Support mode socks5-proxy not support UDP, Temporary, use it carefully.
(but not all socks5 backend server impl UDP, and UDP be rarely used, unless you play a online game work in P2P mode.)
(now, i have some new idea about how to impl UDP, so i will impl it later, in some time.)

AND, the new Auth Support impl not have long running time test, NOW , so please use it carefully.

--

the v1.3 is first auth support version,
if have issue, please -DNeed_ProxyHandshakeAuth=OFF OR back to before-auth and make a new issue.

@roointan
Copy link
Author

Thanks so much! done fast!

@roointan
Copy link
Author

roointan commented Aug 11, 2023

I built the version with the new feature (had to install a more recent boost)
but when trying to use it, I get some logs similar to this by just replacing the old executable with the new one, and it just doesn't work.
I was expecting it to just work out of the box, before adding the auth config.
Any idea why it's happening?

[2023-08-11 17:50:23.066444][0x00007f62e0d7e780][           main][trace] async_accept accept.
[2023-08-11 17:50:23.067957][0x00007f62e0d7e780][           main][trace] incoming connection from : USERIP:52684  on : SOCKS5BALANCERIP:5000
[2023-08-11 17:50:23.068178][0x00007f62e0d7e780][           main][trace] TcpRelaySession start()
[2023-08-11 17:50:23.068886][0x00007f62e0d7e780][           main][trace] getServerByHint:[index:44, name:server45, host:SOCKS5BALANCERIP, port:10044, ]
[2023-08-11 17:50:23.069025][0x00007f62e0d7e780][           main][trace] TcpRelaySession try_connect_upstream() SOCKS5BALANCERIP:10044
[2023-08-11 17:50:23.069195][0x00007f62e0d7e780][           main][trace] async_accept next.
[2023-08-11 17:50:23.069477][0x00007f62e0d7e780][           main][trace] TcpRelaySession do_resolve() SOCKS5BALANCERIP:10044
[2023-08-11 17:50:23.072845][0x00007f62e0d7e780][           main][trace] TcpRelaySession do_connect_upstream()
[2023-08-11 17:50:23.073107][0x00007f62e0d7e780][           main][trace] is socks5
[2023-08-11 17:50:23.073224][0x00007f62e0d7e780][           main][trace] is socks5 no auth
do_tcp_connect on :SOCKS5BALANCERIP:10284: Connection refused
do_tcp_connect on :SOCKS5BALANCERIP:10054: Connection refused
do_tcp_connect on :SOCKS5BALANCERIP:10090: Connection refused
[2023-08-11 17:50:23.115628][0x00007f62e0d7e780][           main][error] do_handshake_client_read: [End of file] . 
[2023-08-11 17:50:23.115768][0x00007f62e0d7e780][           main][trace] ProxyHandshakeAuth::do_whenError()
[2023-08-11 17:50:23.115872][0x00007f62e0d7e780][           main][trace] TcpRelaySession whenError call close(error) error:End of file [asio.misc:2 at /usr/include/boost/asio/detail/reactive_socket_recv_op.hpp:129:5 in function 'static void boost::asio::detail::reactive_socket_recv_op<MutableBufferSequence, Handler, IoExecutor>::do_complete(void*, boost::asio::detail::operation*, const boost::system::error_code&, std::size_t)']
[2023-08-11 17:50:23.116000][0x00007f62e0d7e780][           main][trace] TcpRelaySession::close error:End of file [asio.misc:2 at /usr/include/boost/asio/detail/reactive_socket_recv_op.hpp:129:5 in function 'static void boost::asio::detail::reactive_socket_recv_op<MutableBufferSequence, Handler, IoExecutor>::do_complete(void*, boost::asio::detail::operation*, const boost::system::error_code&, std::size_t)']
[2023-08-11 17:50:23.118684][0x00007f62e0d7e780][           main][trace] ~TcpRelaySession()
[2023-08-11 17:50:23.118809][0x00007f62e0d7e780][           main][trace] TcpRelaySession::close error:Success [system:0]
[2023-08-11 17:50:23.120922][0x00007f62e0d7e780][           main][trace] ~ProxyHandshakeAuth()
[2023-08-11 17:50:23.121046][0x00007f62e0d7e780][           main][trace] ~Socks5ClientImpl()
[2023-08-11 17:50:23.121145][0x00007f62e0d7e780][           main][trace] ~HttpServerImpl()
[2023-08-11 17:50:23.121240][0x00007f62e0d7e780][           main][trace] ~HttpClientImpl()
[2023-08-11 17:50:23.121353][0x00007f62e0d7e780][           main][trace] ~Socks5ServerImpl()

@Lyoko-Jeremie
Copy link
Collaborator

@roointan Hi, i find the bug and fix it now.

please test the v1.3.1


and, the UDP maybe work, i dont have UDP test env now, i think it will work, you can have a try if you need.

@Lyoko-Jeremie
Copy link
Collaborator

Lyoko-Jeremie commented Aug 14, 2023

oh, when i review the code i found that , the ConnectTest are not impl AUTH now,
so the backend alive test are not working when upstream (backend server) enable auth.

this issue only effect case (1) (1) Socks5BalancerAsio -> backend server side (upstream side),
hope it will not effect you, and i will re-impl the ConnectTest compoment to support auth, later.

the case (2) (2) client -> Socks5BalancerAsio side (downstream side) not effect.
or, not use backend server auth, will also not effect by ConnectTest, it will work well like before.

@Lyoko-Jeremie
Copy link
Collaborator

Hi~
about the build question

I built the version with the new feature (had to install a more recent boost)

.

i create the github auto build action, to make the pre-build binary.

if you need deploy multi server, maybe you can use the auto build binary in github action OR in release like this that the binay file copy from github action.

@Lyoko-Jeremie
Copy link
Collaborator

Lyoko-Jeremie commented Aug 21, 2023

Hi~

the Auth Info Statistics be added to Web Monitor now. Release AutoBuild 2

2023-08-21 13_14_39-Socks5BalancerAsio — Firefox Developer Edition

i not sure the i18n work or not. you can modifiy js to force use en-US .

moment.locale('zh-cn');
var getI18nTable = () => {
if (window.navigator.language === "zh-CN") {
// chinese
window.i18nTable = window.i18n.zhCN;
} else {
// english
window.i18nTable = window.i18n.enUS;
}
};
getI18nTable();

change it to :

// moment.locale('zh-cn'); 
  
 var getI18nTable = () => { 
         // english 
         window.i18nTable = window.i18n.enUS; 
 }; 
 getI18nTable(); 

wait your feedback ~

@Lyoko-Jeremie
Copy link
Collaborator

Hi~

the auth support full impl now, add the i18n selector, and add the ping monitor.

you can download the pre-build binary from Release page .

i will close this issue, if you have any problem, please report again, thank you~

@roointan
Copy link
Author

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants