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

unix socket support #378

Merged
merged 9 commits into from
Nov 17, 2023
Merged

unix socket support #378

merged 9 commits into from
Nov 17, 2023

Conversation

cyberb
Copy link
Contributor

@cyberb cyberb commented Nov 16, 2023

Allows using unix socket on both ends:

SYNCV3_BINDADDR=/var/snap/matrix/current/sliding-sync.socket
SYNCV3_SERVER=/var/snap/matrix/current/matrix.socket

Tested in Syncloud (https://github.com/syncloud/matrix) which allows me to use Element X now.

Pull Request Checklist

Signed-off-by: Boris Rybalkin <ribalkin@gmail.com>
Copy link
Member

@kegsay kegsay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall I'm happy with the idea, but there's some extra bits to do to get it over the line:

Thanks for your contribution!

sync2/client.go Outdated Show resolved Hide resolved
sync2/client.go Outdated Show resolved Hide resolved
v3.go Outdated Show resolved Hide resolved
@cyberb
Copy link
Contributor Author

cyberb commented Nov 16, 2023

e2e test use real synapse server which I am not sure even supports unix sockets (dendrite does), I will need to check if there is an env, but even if there is do you want to run all e2e tests on each type (http and unix)?
I would just add one test to check that unix socket client can make requests.

@kegsay
Copy link
Member

kegsay commented Nov 16, 2023

Hmm, good point. Synapse does support unix sockets via SYNAPSE_USE_UNIX_SOCKET=1 in the synapse service image we're using, but I'm not sure you can talk unix sockets to the GHA service container. Running a single test will do, though it isn't super ideal as I'm interested in testing large packet sizes / load.

Let me know how much work this will be, and if it's not really feasible we'll think of something else.

Copy link
Member

@kegsay kegsay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think HomeServerUrl makes things much clearer here, and it adds boilerplate where it is not necessary. Please:

  • revert it back and just add internal.IsUnixSocket(u string) bool and call that in places where you previously had strings.HasPrefix. That is just as easily unit testable should you wish to do so, but please do not add testify for basic equality checks.
  • add a function to map a unix socket string to a unix transport: internal.UnixTransport(u string) http.Transport
  • tie the two functions together in newClient:
func newClient(timeout time.Duration, destinationURL string) *http.Client {
    transport := http.DefaultTransport
    if internal.IsUnixSocket(destinationURL) (
        transport = internal.UnixTransport(destinationURL)
    }
    return &http.Client{
        Timeout: timeout,
        Transport: transport,
    }
}

if !expr {
GetSentryHubFromContextOrDefault(ctx).CaptureException(fmt.Errorf("assertion failed: %s", msg))
}
}

func assert(msg string, expr bool) {
func assertCustom(msg string, expr bool) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the rename?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please revert.

go.mod Outdated
@@ -15,6 +15,7 @@ require (
github.com/pressly/goose/v3 v3.14.0
github.com/prometheus/client_golang v1.13.0
github.com/rs/zerolog v1.29.0
github.com/stretchr/testify v1.8.4
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't add an entire test package just for basic equality checks.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

go mod tidy please.

internal/home_server_url.go Outdated Show resolved Hide resolved
internal/home_server_url.go Outdated Show resolved Hide resolved
if err != nil {
logger.Fatal().Err(err).Msg("failed to serve unix socket")
}
err = os.Chmod(bindAddr, 0755)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please document the respective r/w/x permissions you wish to give to this socket as a comment.

Copy link
Member

@kegsay kegsay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, just a few final minor things:

  • go mod tidy to remove the testify dep.
  • Please document the respective r/w/x permissions you wish to give to this socket as a comment.
  • Revert the change from assert to assertCustom.

Then LGTM, thanks!

@kegsay kegsay merged commit 62d3798 into matrix-org:main Nov 17, 2023
7 checks passed
@cyberb
Copy link
Contributor Author

cyberb commented Nov 17, 2023

Thank you!
Probably this issue can be closed as well: #216

Comment on lines +251 to +252
// TODO: safe default for now (rwxr-xr-x), could be extracted as env variable if needed
err = os.Chmod(bindAddr, 0755)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what is meant by "safe default" here.
Unix sockets don't need the write permissions.

To connect to and use a unix socket as a client, all you need is the read permissions bit.

0755, which translates to u=rwx,go=rw, renders this unix socket world readable, thus making it world-connectable.

Copy link
Contributor Author

@cyberb cyberb Nov 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was under impression that 755 will only allow the owner to use it.
After googling looks like eXecute is not need but read and write are needed to use it.
Ideally we pass it as a parameter, if not then probably 600 is what I wanted.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to unix(7), write permission is required to connect to a unix domain socket.

On Linux, connecting to a stream socket object requires write permission on that socket; sending a datagram to a datagram socket likewise requires write permission on that socket.

I'd suggest to make it at least user and group connectable, that is 0660 (execution bit has no effect).

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First and foremost: Sorry for my original comment.
I was in a bit of a rush when I wrote it, and should just have waited a bit longer before commenting.

Multiple /bit flips/ happened in my original comment, which I want to point out:

  1. write perms are needed to connect and talk over a unix socket, not read, as @n3vu0r correctly pointed out.
  2. 0755 does not translate to u=rwx,go=rw but rather u=rwx,go=rx.
  3. Which in turn makes, as intended, the socket not world-connectable but rather only by the owner itself.

I just was very happy to see unix socket support implemented so soon, but then saw some unusual permission bits.

Given I worked on unix socket permission bits as part of caddyserver/caddy#4741, I figured I should comment. Which then lead to that hastily, and more importantly, incorrect comment. Sorry for that.

According to the current unix(7), only write perms are needed.
There are, however, still a lot of old unix(7) versions hosted on the web, which still mention read and write being needed.

For more details on this, see caddyserver/caddy#4741 (comment).


I'd suggest to make it at least user and group connectable, that is 0660 (execution bit has no effect).

I would suggest the same, but without read, so 0220.

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

Successfully merging this pull request may close these issues.

4 participants